From 63af0dbca9f72c5c624a5b72a7d88f3bf8cff009 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 12 Jun 2013 16:22:01 -0500 Subject: [PATCH 001/174] Initial commit. --- .gitignore | 28 ++++++++++++++++++++++++++++ README.md | 4 ++++ 2 files changed, 32 insertions(+) create mode 100644 .gitignore create mode 100644 README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..5b97dbba --- /dev/null +++ b/.gitignore @@ -0,0 +1,28 @@ +# Temp files +*~ + +# Log files +*.log + +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe diff --git a/README.md b/README.md new file mode 100644 index 00000000..f8bf0ac0 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +btcscript +========= + +Package btcscript implements the bitcoin transaction scripts. From 119777015909a98595885c8d80cb8d06aff7aab8 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 12 Jun 2013 16:35:27 -0500 Subject: [PATCH 002/174] Initial implementation. --- LICENSE | 13 + README.md | 73 +- address.go | 190 +++ address_test.go | 245 ++++ cov_report.sh | 17 + doc.go | 59 + internal_test.go | 44 + log.go | 65 + opcode.go | 1603 +++++++++++++++++++++++ opcode_test.go | 3104 +++++++++++++++++++++++++++++++++++++++++++++ script.go | 697 ++++++++++ script_test.go | 1060 ++++++++++++++++ stack.go | 350 +++++ stack_test.go | 818 ++++++++++++ test_coverage.txt | 138 ++ 15 files changed, 8475 insertions(+), 1 deletion(-) create mode 100644 LICENSE create mode 100644 address.go create mode 100644 address_test.go create mode 100644 cov_report.sh create mode 100644 doc.go create mode 100644 internal_test.go create mode 100644 log.go create mode 100644 opcode.go create mode 100644 opcode_test.go create mode 100644 script.go create mode 100644 script_test.go create mode 100644 stack.go create mode 100644 stack_test.go create mode 100644 test_coverage.txt diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..62a53cea --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2013 Conformal Systems LLC. + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/README.md b/README.md index f8bf0ac0..28662ad6 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,75 @@ btcscript ========= -Package btcscript implements the bitcoin transaction scripts. +Package btcscript implements the bitcoin transaction scripts. There is a test +suite which is aiming to reach 100% code coverage. See +`test_coverage.txt` for the current coverage (using gocov). On a +UNIX-like OS, the script `cov_report.sh` can be used to generate the +report. Package btcscript is licensed under the liberal ISC license. + +This package is one of the core packages from btcd, an alternative full-node +implementation of bitcoin which is under active development by Conformal. +Although it was primarily written for btcd, this package has intentionally been +designed so it can be used as a standalone package for any projects needing to +use or validate bitcoin transaction scripts. + +## Bitcoin Scripts + +Bitcoin provides a stack-based, FORTH-like langauge for the scripts in +the bitcoin transactions. This language is not turing complete +although it is still fairly powerful. A description of the language +can be found at https://en.bitcoin.it/wiki/Script + +## Sample Use + +```Go + pkscript := txS.TxOut[origintxidx].PkScript + engine, err := btcscript.NewScript(sigScript, pkscript, txInIdx, + txValidator, pver, + timestamp.After(btcscript.Bip16Activation)) + err = engine.Execute() +``` + +## Documentation + +Full `go doc` style documentation for the project can be viewed online without +installing this package by using the GoDoc site +[here](http://godoc.org/github.com/conformal/btcscript). + +You can also view the documentation locally once the package is installed with +the `godoc` tool by running `godoc -http=":6060"` and pointing your browser to +http://localhost:6060/pkg/github.com/conformal/btcscript + +## Installation + +```bash +$ go get github.com/conformal/btcscript +``` + +## TODO + +- Increase test coverage to 100% + +## GPG Verification Key + +All official release tags are signed by Conformal so users can ensure the code +has not been tampered with and is coming from Conformal. To verify the +signature perform the following: + +- Download the public key from the Conformal website at + https://opensource.conformal.com/GIT-GPG-KEY-conformal.txt + +- Import the public key into your GPG keyring: + ```bash + gpg --import GIT-GPG-KEY-conformal.txt + ``` + +- Verify the release tag with the following command where `TAG_NAME` is a + placeholder for the specific tag: + ```bash + git tag -v TAG_NAME + ``` + +## License + +Package btcscript is licensed under the liberal ISC License. diff --git a/address.go b/address.go new file mode 100644 index 00000000..02eacc8a --- /dev/null +++ b/address.go @@ -0,0 +1,190 @@ +// Copyright (c) 2013 Conformal Systems LLC. +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcscript + +import ( + "github.com/conformal/btcutil" + "github.com/conformal/btcwire" +) + +// ScriptType is an enum type that represents the type of a script. It is +// returned from ScriptToAddress as part of the metadata about the script. +// It implements the Stringer interface for nice printing. +type ScriptType int + +// String Converts the enumeration to a nice string value instead of a number. +func (t ScriptType) String() string { + if int(t) > len(scriptTypeToName) || int(t) < 0 { + return "Invalid" + } + return scriptTypeToName[t] +} + +// Constant types representing known types of script found in the wild +const ( + ScriptUnknown ScriptType = iota + ScriptAddr + ScriptPubKey + ScriptStrange + ScriptGeneration +) + +var scriptTypeToName = []string{ + ScriptUnknown: "Unknown", + ScriptAddr: "Addr", + ScriptPubKey: "Pubkey", + ScriptStrange: "Strange", + ScriptGeneration: "Generation", // ScriptToAddress does not recieve enough information to identify Generation scripts. +} + +type pkformat struct { + addrtype ScriptType + parsetype int + length int + databytes []pkbytes + allowmore bool +} + +type pkbytes struct { + off int + val byte +} + +const ( + scrPayAddr = iota + scrCollectAddr + scrCollectAddrComp + scrGeneratePubkeyAddr + scrPubkeyAddr + scrPubkeyAddrComp + scrNoAddr +) + +// ScriptToAddress extracts a payment address and the type out of a PkScript +func ScriptToAddress(script []byte) (ScriptType, string, error) { + // Currently this only understands one form of PkScript + validformats := []pkformat{ + {ScriptAddr, scrPayAddr, 25, []pkbytes{{0, OP_DUP}, {1, OP_HASH160}, {2, OP_DATA_20}, {23, OP_EQUALVERIFY}, {24, OP_CHECKSIG}}, true}, + {ScriptAddr, scrCollectAddr, 142, []pkbytes{{0, OP_DATA_75}, {76, OP_DATA_65}}, false}, + {ScriptAddr, scrCollectAddr, 141, []pkbytes{{0, OP_DATA_74}, {75, OP_DATA_65}}, false}, + {ScriptAddr, scrCollectAddr, 140, []pkbytes{{0, OP_DATA_73}, {74, OP_DATA_65}}, false}, + {ScriptAddr, scrCollectAddr, 139, []pkbytes{{0, OP_DATA_72}, {73, OP_DATA_65}}, false}, + {ScriptAddr, scrCollectAddr, 138, []pkbytes{{0, OP_DATA_71}, {72, OP_DATA_65}}, false}, + {ScriptAddr, scrCollectAddr, 137, []pkbytes{{0, OP_DATA_70}, {71, OP_DATA_65}}, false}, + {ScriptAddr, scrCollectAddr, 136, []pkbytes{{0, OP_DATA_69}, {70, OP_DATA_65}}, false}, + {ScriptAddr, scrCollectAddrComp, 110, []pkbytes{{0, OP_DATA_75}, {76, OP_DATA_33}}, false}, + {ScriptAddr, scrCollectAddrComp, 109, []pkbytes{{0, OP_DATA_74}, {75, OP_DATA_33}}, false}, + {ScriptAddr, scrCollectAddrComp, 108, []pkbytes{{0, OP_DATA_73}, {74, OP_DATA_33}}, false}, + {ScriptAddr, scrCollectAddrComp, 107, []pkbytes{{0, OP_DATA_72}, {73, OP_DATA_33}}, false}, + {ScriptAddr, scrCollectAddrComp, 106, []pkbytes{{0, OP_DATA_71}, {72, OP_DATA_33}}, false}, + {ScriptAddr, scrCollectAddrComp, 105, []pkbytes{{0, OP_DATA_70}, {71, OP_DATA_33}}, false}, + {ScriptAddr, scrCollectAddrComp, 104, []pkbytes{{0, OP_DATA_69}, {70, OP_DATA_33}}, false}, + {ScriptPubKey, scrGeneratePubkeyAddr, 74, []pkbytes{{0, OP_DATA_73}}, false}, + {ScriptPubKey, scrGeneratePubkeyAddr, 73, []pkbytes{{0, OP_DATA_72}}, false}, + {ScriptPubKey, scrGeneratePubkeyAddr, 72, []pkbytes{{0, OP_DATA_71}}, false}, + {ScriptPubKey, scrGeneratePubkeyAddr, 71, []pkbytes{{0, OP_DATA_70}}, false}, + {ScriptPubKey, scrGeneratePubkeyAddr, 70, []pkbytes{{0, OP_DATA_69}}, false}, + {ScriptPubKey, scrPubkeyAddr, 67, []pkbytes{{0, OP_DATA_65}, {66, OP_CHECKSIG}}, true}, + {ScriptPubKey, scrPubkeyAddrComp, 35, []pkbytes{{0, OP_DATA_33}, {34, OP_CHECKSIG}}, true}, + {ScriptStrange, scrNoAddr, 33, []pkbytes{{0, OP_DATA_32}}, false}, + {ScriptStrange, scrNoAddr, 33, []pkbytes{{0, OP_HASH160}, {1, OP_DATA_20}, {22, OP_EQUAL}}, false}, + } + + var format pkformat + var success bool + for _, format = range validformats { + if format.length != len(script) { + if len(script) < format.length { + continue + } + if !format.allowmore { + continue + } + } + success = true + for _, pkbyte := range format.databytes { + if pkbyte.off >= len(script) { + success = false + break + } + if script[pkbyte.off] != pkbyte.val { + log.Tracef("off at byte %v %v %v", pkbyte.off, script[pkbyte.off], pkbyte.val) + success = false + break + } else { + log.Tracef("match at byte %v: ok", pkbyte.off) + } + } + if success == true { + break + } + } + + if success == false && len(script) > 1 { + // check for a few special case + if script[len(script)-1] == OP_CHECK_MULTISIG { + // Multisig ScriptPubKey + return ScriptStrange, "Unknown", nil + } + if script[0] == OP_0 && (len(script) <= 75 && byte(len(script)) == script[1]+2) { + // Multisig ScriptSig + return ScriptStrange, "Unknown", nil + } + if script[0] == OP_HASH160 && len(script) == 23 && script[22] == OP_EQUAL { + // Multisig ScriptSig + return ScriptStrange, "Unknown", nil + } + if script[0] == OP_DATA_36 && len(script) == 37 { + // Multisig ScriptSig + return ScriptStrange, "Unknown", nil + } + + return ScriptUnknown, "Unknown", StackErrUnknownAddress + } + + var atype byte + var abuf []byte + var addr string + switch format.parsetype { + case scrPayAddr: + atype = 0x00 + abuf = script[3:23] + case scrCollectAddr: + // script is replaced with the md160 of the pubkey + slen := len(script) + pubkey := script[slen-65:] + abuf = calcHash160(pubkey) + case scrCollectAddrComp: + // script is replaced with the md160 of the pubkey + slen := len(script) + pubkey := script[slen-33:] + abuf = calcHash160(pubkey) + case scrGeneratePubkeyAddr: + atype = 0x00 + addr = "Unknown" + case scrNoAddr: + addr = "Unknown" + case scrPubkeyAddr: + atype = 0x00 + pubkey := script[1:66] + abuf = calcHash160(pubkey) + case scrPubkeyAddrComp: + atype = 0x00 + pubkey := script[1:34] + abuf = calcHash160(pubkey) + default: + log.Warnf("parsetype is %v", format.parsetype) + } + + if abuf != nil { + addrbytes := append([]byte{atype}, abuf[:]...) + + cksum := btcwire.DoubleSha256(addrbytes) + addrbytes = append(addrbytes, cksum[:4]...) + addr = btcutil.Base58Encode(addrbytes) + } + + return format.addrtype, addr, nil +} diff --git a/address_test.go b/address_test.go new file mode 100644 index 00000000..d1f3f96a --- /dev/null +++ b/address_test.go @@ -0,0 +1,245 @@ +// Copyright (c) 2013 Conformal Systems LLC. +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. +package btcscript_test + +import ( + "github.com/conformal/btcscript" + "testing" +) + +type addressTest struct { + script []byte + address string + shouldFail error + class btcscript.ScriptType +} + +var addressTests = []addressTest{ + {script: []byte{btcscript.OP_DATA_65, + 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, + 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, + 0x1e, 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, + 0x2e, 0xca, 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, + 0x5c, 0xb2, 0xe0, 0xea, 0xdd, 0xfb, 0x84, 0xcc, + 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, + 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, + 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, + 0xa3, btcscript.OP_CHECKSIG}, + address: "12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S", + class: btcscript.ScriptPubKey, + }, + {script: []byte{btcscript.OP_DATA_65, + 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, + 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, + 0x1e, 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, + 0x2e, 0xca, 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, + 0x5c, 0xb2, 0xe0, 0xea, 0xdd, 0xfb, 0x84, 0xcc, + 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, + 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, + 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, + 0xa3}, + shouldFail: btcscript.StackErrUnknownAddress, + }, + {script: []byte{btcscript.OP_DATA_71, + 0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69, + 0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, + 0xa1, 0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, + 0xe9, 0xd6, 0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, + 0x5f, 0xb8, 0xcd, 0x41, 0x02, 0x20, 0x18, 0x15, + 0x22, 0xec, 0x8e, 0xca, 0x07, 0xde, 0x48, 0x60, + 0xa4, 0xac, 0xdd, 0x12, 0x90, 0x9d, 0x83, 0x1c, + 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22, 0x08, 0x22, + 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09, 0x01}, + address: "Unknown", + class: btcscript.ScriptPubKey, + }, + {script: []byte{btcscript.OP_DUP, btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0xad, 0x06, 0xdd, 0x6d, 0xde, 0xe5, 0x5c, 0xbc, + 0xa9, 0xa9, 0xe3, 0x71, 0x3b, 0xd7, 0x58, 0x75, + 0x09, 0xa3, 0x05, 0x64, + btcscript.OP_EQUALVERIFY, btcscript.OP_CHECKSIG, + }, + address: "1Gmt8AzabtngttF3PcZzLR1p7uCMaHNuGY", + class: btcscript.ScriptAddr, + }, + {script: []byte{btcscript.OP_DATA_73, + 0x30, 0x46, 0x02, 0x21, 0x00, 0xdd, 0xc6, 0x97, + 0x38, 0xbf, 0x23, 0x36, 0x31, 0x8e, 0x4e, 0x04, + 0x1a, 0x5a, 0x77, 0xf3, 0x05, 0xda, 0x87, 0x42, + 0x8a, 0xb1, 0x60, 0x6f, 0x02, 0x32, 0x60, 0x01, + 0x78, 0x54, 0x35, 0x0d, 0xdc, 0x02, 0x21, 0x00, + 0x81, 0x7a, 0xf0, 0x9d, 0x2e, 0xec, 0x36, 0x86, + 0x2d, 0x16, 0x00, 0x98, 0x52, 0xb7, 0xe3, 0xa0, + 0xf6, 0xdd, 0x76, 0x59, 0x82, 0x90, 0xb7, 0x83, + 0x4e, 0x14, 0x53, 0x66, 0x03, 0x67, 0xe0, 0x7a, + 0x01, + btcscript.OP_DATA_65, + 0x04, 0xcd, 0x42, 0x40, 0xc1, 0x98, 0xe1, 0x25, + 0x23, 0xb6, 0xf9, 0xcb, 0x9f, 0x5b, 0xed, 0x06, + 0xde, 0x1b, 0xa3, 0x7e, 0x96, 0xa1, 0xbb, 0xd1, + 0x37, 0x45, 0xfc, 0xf9, 0xd1, 0x1c, 0x25, 0xb1, + 0xdf, 0xf9, 0xa5, 0x19, 0x67, 0x5d, 0x19, 0x88, + 0x04, 0xba, 0x99, 0x62, 0xd3, 0xec, 0xa2, 0xd5, + 0x93, 0x7d, 0x58, 0xe5, 0xa7, 0x5a, 0x71, 0x04, + 0x2d, 0x40, 0x38, 0x8a, 0x4d, 0x30, 0x7f, 0x88, + 0x7d}, + address: "16tRBxwU7t5hEHaPLqiE35gS3jaGBppraH", + class: btcscript.ScriptAddr, + }, + {script: []byte{btcscript.OP_DATA_73, + 0x30, 0x46, 0x02, 0x21, 0x00, 0xac, 0x7e, 0x4e, + 0x27, 0xf2, 0xb1, 0x1c, 0xb8, 0x6f, 0xb5, 0xaa, + 0x87, 0x2a, 0xb9, 0xd3, 0x2c, 0xdc, 0x08, 0x33, + 0x80, 0x73, 0x3e, 0x3e, 0x98, 0x47, 0xff, 0x77, + 0xa0, 0x69, 0xcd, 0xdf, 0xab, 0x02, 0x21, 0x00, + 0xc0, 0x4c, 0x3e, 0x6f, 0xfe, 0x88, 0xa1, 0x5b, + 0xc5, 0x07, 0xb8, 0xe5, 0x71, 0xaa, 0x35, 0x92, + 0x8a, 0xcf, 0xe1, 0x5a, 0x4a, 0x23, 0x20, 0x1b, + 0x08, 0xfe, 0x3c, 0x7b, 0x3c, 0x97, 0xc8, 0x8f, + 0x01, + btcscript.OP_DATA_33, + 0x02, 0x40, 0x05, 0xc9, 0x45, 0xd8, 0x6a, 0xc6, + 0xb0, 0x1f, 0xb0, 0x42, 0x58, 0x34, 0x5a, 0xbe, + 0xa7, 0xa8, 0x45, 0xbd, 0x25, 0x68, 0x9e, 0xdb, + 0x72, 0x3d, 0x5a, 0xd4, 0x06, 0x8d, 0xdd, 0x30, + 0x36, + }, + address: "1272555ceTPn2WepjzVgFESWdfNQjqdjgp", + class: btcscript.ScriptAddr, + }, + {script: []byte{btcscript.OP_DATA_32, + 0x30, 0x46, 0x02, 0x21, 0x00, 0xac, 0x7e, 0x4e, + 0x27, 0xf2, 0xb1, 0x1c, 0xb8, 0x6f, 0xb5, 0xaa, + 0x87, 0x2a, 0xb9, 0xd3, 0x2c, 0xdc, 0x08, 0x33, + 0x80, 0x73, 0x3e, 0x3e, 0x98, 0x47, 0xff, 0x77, + }, + address: "Unknown", + class: btcscript.ScriptStrange, + }, + {script: []byte{btcscript.OP_DATA_33, + 0x02, 0x40, 0x05, 0xc9, 0x45, 0xd8, 0x6a, 0xc6, + 0xb0, 0x1f, 0xb0, 0x42, 0x58, 0x34, 0x5a, 0xbe, + 0xa7, 0xa8, 0x45, 0xbd, 0x25, 0x68, 0x9e, 0xdb, + 0x72, 0x3d, 0x5a, 0xd4, 0x06, 0x8d, 0xdd, 0x30, + 0x36, + btcscript.OP_CHECKSIG, + }, + address: "1272555ceTPn2WepjzVgFESWdfNQjqdjgp", + class: btcscript.ScriptPubKey, + }, + {script: []byte{btcscript.OP_DATA_33, + 0x02, 0x40, 0x05, 0xc9, 0x45, 0xd8, 0x6a, 0xc6, + 0xb0, 0x1f, 0xb0, 0x42, 0x58, 0x34, 0x5a, 0xbe, + 0xa7, 0xa8, 0x45, 0xbd, 0x25, 0x68, 0x9e, 0xdb, + 0x72, 0x3d, 0x5a, 0xd4, 0x06, 0x8d, 0xdd, 0x30, + 0x36, + btcscript.OP_CHECK_MULTISIG, // note this isn't a real tx + }, + address: "Unknown", + class: btcscript.ScriptStrange, + }, + {script: []byte{btcscript.OP_0, btcscript.OP_DATA_33, + 0x02, 0x40, 0x05, 0xc9, 0x45, 0xd8, 0x6a, 0xc6, + 0xb0, 0x1f, 0xb0, 0x42, 0x58, 0x34, 0x5a, 0xbe, + 0xa7, 0xa8, 0x45, 0xbd, 0x25, 0x68, 0x9e, 0xdb, + 0x72, 0x3d, 0x5a, 0xd4, 0x06, 0x8d, 0xdd, 0x30, + 0x36, // note this isn't a real tx + }, + address: "Unknown", + class: btcscript.ScriptStrange, + }, + {script: []byte{btcscript.OP_HASH160, btcscript.OP_DATA_20, + 0x02, 0x40, 0x05, 0xc9, 0x45, 0xd8, 0x6a, 0xc6, + 0xb0, 0x1f, 0xb0, 0x42, 0x58, 0x34, 0x5a, 0xbe, + 0xa7, 0xa8, 0x45, 0xbd, + btcscript.OP_EQUAL, // note this isn't a real tx + }, + address: "Unknown", + class: btcscript.ScriptStrange, + }, + {script: []byte{btcscript.OP_DATA_36, + 0x02, 0x40, 0x05, 0xc9, 0x45, 0xd8, 0x6a, 0xc6, + 0xb0, 0x1f, 0xb0, 0x42, 0x58, 0x34, 0x5a, 0xbe, + 0xb0, 0x1f, 0xb0, 0x42, 0x58, 0x34, 0x5a, 0xbe, + 0xb0, 0x1f, 0xb0, 0x42, 0x58, 0x34, 0x5a, 0xbe, + 0xa7, 0xa8, 0x45, 0xbd, + // note this isn't a real tx + }, + address: "Unknown", + class: btcscript.ScriptStrange, + }, +} + +func TestAddresses(t *testing.T) { + for i, s := range addressTests { + class, address, err := btcscript.ScriptToAddress(s.script) + if s.shouldFail != nil { + if err != s.shouldFail { + t.Errorf("Address test %v failed is err [%v] should be [%v]", i, err, s.shouldFail) + } + } else { + if err != nil { + t.Errorf("Address test %v failed err %v", i, err) + } else { + if s.address != address { + t.Errorf("Address test %v mismatch is [%v] want [%v]", i, address, s.address) + } + if s.class != class { + t.Errorf("Address test %v class mismatch is [%v] want [%v]", i, class, s.class) + } + } + } + + } +} + +type stringifyTest struct { + name string + scripttype btcscript.ScriptType + stringed string +} + +var stringifyTests = []stringifyTest{ + stringifyTest{ + name: "unknown", + scripttype: btcscript.ScriptUnknown, + stringed: "Unknown", + }, + stringifyTest{ + name: "addr", + scripttype: btcscript.ScriptAddr, + stringed: "Addr", + }, + stringifyTest{ + name: "pubkey", + scripttype: btcscript.ScriptPubKey, + stringed: "Pubkey", + }, + stringifyTest{ + name: "strange", + scripttype: btcscript.ScriptStrange, + stringed: "Strange", + }, + stringifyTest{ + name: "generation", + scripttype: btcscript.ScriptGeneration, + stringed: "Generation", + }, + stringifyTest{ + name: "not in enum", + scripttype: btcscript.ScriptType(255), + stringed: "Invalid", + }, +} + +func TestStringify(t *testing.T) { + for _, test := range stringifyTests { + typeString := test.scripttype.String() + if typeString != test.stringed { + t.Errorf("%s: got \"%s\" expected \"%s\"", test.name, + typeString, test.stringed) + } + } +} diff --git a/cov_report.sh b/cov_report.sh new file mode 100644 index 00000000..307f05b7 --- /dev/null +++ b/cov_report.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +# This script uses gocov to generate a test coverage report. +# The gocov tool my be obtained with the following command: +# go get github.com/axw/gocov/gocov +# +# It will be installed to $GOPATH/bin, so ensure that location is in your $PATH. + +# Check for gocov. +type gocov >/dev/null 2>&1 +if [ $? -ne 0 ]; then + echo >&2 "This script requires the gocov tool." + echo >&2 "You may obtain it with the following command:" + echo >&2 "go get github.com/axw/gocov/gocov" + exit 1 +fi +gocov test | gocov report diff --git a/doc.go b/doc.go new file mode 100644 index 00000000..0fb28f23 --- /dev/null +++ b/doc.go @@ -0,0 +1,59 @@ +// Copyright (c) 2013 Conformal Systems LLC. +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +/* +Package btcscript implements bitcoin transaction scripts. + +A complete description of the script language used by bitcoin can be found at +https://en.bitcoin.it/wiki/Script. The following only serves as a quick +overview to provide information on how to use the package. + +This package provides data structures and functions to parse and execute +bitcoin transaction scripts. + +Script Overview + +Bitcoin transaction scripts are written in a stack-base, FORTH-like language. + +The bitcoin script language consists of a number of opcodes which fall into +several categories such pushing and popping data to and from the stack, +performing basic and bitwise arithmetic, conditional branching, comparing +hashes, and checking cryptographic signatures. Scripts are processed from left +to right and intentionally do not provide loops. + +The vast majority of Bitcoin scripts at the time of this writing are of several +standard forms which consist of a spender providing a public key and a signature +which proves the spender owns the associated private key. This information +is used to prove the the spender is authorized to perform the transaction. + +One benefit of using a scripting language is added flexibility in specifying +what conditions must be met in order to spend bitcoins. + +Usage + +The usage of this package consists of creating a new script engine for a pair +of transaction inputs and outputs and using the engine to execute the scripts. + +The following function is an example of how to create and execute a script +engine to validate a transaction. + + // ValidateTx validates the txIdx'th input of tx. The output transaction + // corresponding to the this input is the txInIdx'th output of txIn. The + // block timestamp of tx is timestamp and the protocol version involved + // is pver. + func ValidateTx(tx *btcwire.MsgTx, txIdx int, txIn *btcwire.MsgTx, txInIdx int, pver int, timestamp time.Time) { + pkScript := txIn.TxOut[txInIdx].PkScript + sigScript := tx.txIn[TxIdx] + engine, err := btcscript.NewScript(sigScript, pkScript, txInIdx, + tx, pver, timestamp.After(btcscript.Bip16Activation)) + return engine.Execute() + } + +Errors + +Errors returned by this package are of the form btcscript.StackErrX where X +indicates the specific error. See Variables in the package documentation for a +full list. +*/ +package btcscript diff --git a/internal_test.go b/internal_test.go new file mode 100644 index 00000000..a4196b31 --- /dev/null +++ b/internal_test.go @@ -0,0 +1,44 @@ +// Copyright (c) 2013 Conformal Systems LLC. +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcscript + +// this file is present to export some internal interfaces so that we can +// test them reliably. + +func TstRemoveOpcode(pkscript []byte, opcode byte) ([]byte, error) { + pops, err := parseScript(pkscript) + if err != nil { + return nil, err + } + pops = removeOpcode(pops, opcode) + return unparseScript(pops), nil +} + +func TstRemoveOpcodeByData(pkscript []byte, data []byte) ([]byte, error) { + pops, err := parseScript(pkscript) + if err != nil { + return nil, err + } + pops = removeOpcodeByData(pops, data) + return unparseScript(pops), nil +} + +type TstScriptType scriptType + +const ( + TstPubKeyTy TstScriptType = TstScriptType(pubKeyTy) + TstPubKeyHashTy = TstScriptType(pubKeyHashTy) + TstScriptHashTy = TstScriptType(scriptHashTy) + TstMultiSigTy = TstScriptType(multiSigTy) + TstNonStandardTy = TstScriptType(nonStandardTy) +) + +func TstTypeOfScript(script []byte) TstScriptType { + pops, err := parseScript(script) + if err != nil { + return TstNonStandardTy + } + return TstScriptType(typeOfScript(pops)) +} diff --git a/log.go b/log.go new file mode 100644 index 00000000..28faf744 --- /dev/null +++ b/log.go @@ -0,0 +1,65 @@ +// Copyright (c) 2013 Conformal Systems LLC. +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcscript + +import ( + "errors" + "github.com/conformal/seelog" + "io" +) + +// log is a logger that is initialized with no output filters. This +// means the package will not perform any logging by default until the caller +// requests it. +var log seelog.LoggerInterface + +// The default amount of logging is none. +func init() { + DisableLog() +} + +// DisableLog disables all library log output. Logging output is disabled +// by default until either UseLogger or SetLogWriter are called. +func DisableLog() { + log = seelog.Disabled +} + +// UseLogger uses a specified Logger to output package logging info. +// This should be used in preference to SetLogWriter if the caller is also +// using seelog. +func UseLogger(logger seelog.LoggerInterface) { + log = logger +} + +// SetLogWriter uses a specified io.Writer to output package logging info. +// This allows a caller to direct package logging output without needing a +// dependency on seelog. If the caller is also using seelog, UseLogger should +// be used instead. +func SetLogWriter(w io.Writer) error { + if w == nil { + return errors.New("nil writer") + } + + l, err := seelog.LoggerFromWriterWithMinLevel(w, seelog.TraceLvl) + if err != nil { + return err + } + + UseLogger(l) + return nil +} + +// LogClosure is a closure that can be printed with %v to be used to +// generate expensive-to-create data for a detailed log level and avoid doing +// the work if the data isn't printed. +type logClosure func() string + +func (c logClosure) String() string { + return c() +} + +func newLogClosure(c func() string) logClosure { + return logClosure(c) +} diff --git a/opcode.go b/opcode.go new file mode 100644 index 00000000..504d8ff3 --- /dev/null +++ b/opcode.go @@ -0,0 +1,1603 @@ +// Copyright (c) 2013 Conformal Systems LLC. +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcscript + +import ( + "bytes" + "code.google.com/p/go.crypto/ripemd160" + "crypto/ecdsa" + "crypto/sha1" + "crypto/sha256" + "fmt" + "github.com/conformal/btcwire" + "github.com/davecgh/go-spew/spew" + "hash" + "math/big" + "opensource.conformal.com/go/btcd/btcec" +) + +// An opcode defines the information related to a btcscript opcode. +// opfunc if present is the function to call to perform the opcode on +// the script. The current script is passed in as a slice with the firs +// member being the opcode itself. +type opcode struct { + value byte + name string + length int + opfunc func(*parsedOpcode, *Script) error + parsefunc func(*opcode, *Script, []byte) error +} + +// These constants are the values of the official opcode used on the btc wiki, +// in bitcoind and in most if not all other references and software related to +// handling BTC scripts. +const ( + OP_FALSE byte = 0 // AKA OP_0 + OP_0 = 0 + OP_DATA_1 = 1 + OP_DATA_2 = 2 + OP_DATA_3 = 3 + OP_DATA_4 = 4 + OP_DATA_5 = 5 + OP_DATA_6 = 6 + OP_DATA_7 = 7 + OP_DATA_8 = 8 + OP_DATA_9 = 9 + OP_DATA_10 = 10 + OP_DATA_11 = 11 + OP_DATA_12 = 12 + OP_DATA_13 = 13 + OP_DATA_14 = 14 + OP_DATA_15 = 15 + OP_DATA_16 = 16 + OP_DATA_17 = 17 + OP_DATA_18 = 18 + OP_DATA_19 = 19 + OP_DATA_20 = 20 + OP_DATA_21 = 21 + OP_DATA_22 = 22 + OP_DATA_23 = 23 + OP_DATA_24 = 24 + OP_DATA_25 = 25 + OP_DATA_26 = 26 + OP_DATA_27 = 27 + OP_DATA_28 = 28 + OP_DATA_29 = 29 + OP_DATA_30 = 30 + OP_DATA_31 = 31 + OP_DATA_32 = 32 + OP_DATA_33 = 33 + OP_DATA_34 = 34 + OP_DATA_35 = 35 + OP_DATA_36 = 36 + OP_DATA_37 = 37 + OP_DATA_38 = 38 + OP_DATA_39 = 39 + OP_DATA_40 = 40 + OP_DATA_41 = 41 + OP_DATA_42 = 42 + OP_DATA_43 = 43 + OP_DATA_44 = 44 + OP_DATA_45 = 45 + OP_DATA_46 = 46 + OP_DATA_47 = 47 + OP_DATA_48 = 48 + OP_DATA_49 = 49 + OP_DATA_50 = 50 + OP_DATA_51 = 51 + OP_DATA_52 = 52 + OP_DATA_53 = 53 + OP_DATA_54 = 54 + OP_DATA_55 = 55 + OP_DATA_56 = 56 + OP_DATA_57 = 57 + OP_DATA_58 = 58 + OP_DATA_59 = 59 + OP_DATA_60 = 60 + OP_DATA_61 = 61 + OP_DATA_62 = 62 + OP_DATA_63 = 63 + OP_DATA_64 = 64 + OP_DATA_65 = 65 + OP_DATA_66 = 66 + OP_DATA_67 = 67 + OP_DATA_68 = 68 + OP_DATA_69 = 69 + OP_DATA_70 = 70 + OP_DATA_71 = 71 + OP_DATA_72 = 72 + OP_DATA_73 = 73 + OP_DATA_74 = 74 + OP_DATA_75 = 75 + OP_PUSHDATA1 = 76 + OP_PUSHDATA2 = 77 + OP_PUSHDATA4 = 78 + OP_1NEGATE = 79 + OP_RESERVED = 80 + OP_1 = 81 // AKA OP_TRUE + OP_TRUE = 81 + OP_2 = 82 + OP_3 = 83 + OP_4 = 84 + OP_5 = 85 + OP_6 = 86 + OP_7 = 87 + OP_8 = 88 + OP_9 = 89 + OP_10 = 90 + OP_11 = 91 + OP_12 = 92 + OP_13 = 93 + OP_14 = 94 + OP_15 = 95 + OP_16 = 96 + OP_NOP = 97 + OP_VER = 98 + OP_IF = 99 + OP_NOTIF = 100 + OP_VERIF = 101 + OP_VERNOTIF = 102 + OP_ELSE = 103 + OP_ENDIF = 104 + OP_VERIFY = 105 + OP_RETURN = 106 + OP_TOALTSTACK = 107 + OP_FROMALTSTACK = 108 + OP_2DROP = 109 + OP_2DUP = 110 + OP_3DUP = 111 + OP_2OVER = 112 + OP_2ROT = 113 + OP_2SWAP = 114 + OP_IFDUP = 115 + OP_DEPTH = 116 + OP_DROP = 117 + OP_DUP = 118 + OP_NIP = 119 + OP_OVER = 120 + OP_PICK = 121 + OP_ROLL = 122 + OP_ROT = 123 + OP_SWAP = 124 + OP_TUCK = 125 + OP_CAT = 126 + OP_SUBSTR = 127 + OP_LEFT = 128 + OP_RIGHT = 129 + OP_SIZE = 130 + OP_INVERT = 131 + OP_AND = 132 + OP_OR = 133 + OP_XOR = 134 + OP_EQUAL = 135 + OP_EQUALVERIFY = 136 + OP_RESERVED1 = 137 + OP_RESERVED2 = 138 + OP_1ADD = 139 + OP_1SUB = 140 + OP_2MUL = 141 + OP_2DIV = 142 + OP_NEGATE = 143 + OP_ABS = 144 + OP_NOT = 145 + OP_0NOTEQUAL = 146 + OP_ADD = 147 + OP_SUB = 148 + OP_MUL = 149 + OP_DIV = 150 + OP_MOD = 151 + OP_LSHIFT = 152 + OP_RSHIFT = 153 + OP_BOOLAND = 154 + OP_BOOLOR = 155 + OP_NUMEQUAL = 156 + OP_NUMEQUALVERIFY = 157 + OP_NUMNOTEQUAL = 158 + OP_LESSTHAN = 159 + OP_GREATERTHAN = 160 + OP_LESSTHANOREQUAL = 161 + OP_GREATERTHANOREQUAL = 162 + OP_MIN = 163 + OP_MAX = 164 + OP_WITHIN = 165 + OP_RIPEMD160 = 166 + OP_SHA1 = 167 + OP_SHA256 = 168 + OP_HASH160 = 169 + OP_HASH256 = 170 + OP_CODESEPARATOR = 171 + OP_CHECKSIG = 172 + OP_CHECKSIGVERIFY = 173 + OP_CHECK_MULTISIG = 174 + OP_CHECKMULTISIGVERIFY = 175 + OP_NOP1 = 176 + OP_NOP2 = 177 + OP_NOP3 = 178 + OP_NOP4 = 179 + OP_NOP5 = 180 + OP_NOP6 = 181 + OP_NOP7 = 182 + OP_NOP8 = 183 + OP_NOP9 = 184 + OP_NOP10 = 185 + OP_PUBKEYHASH = 253 // bitcoind internal, for completeness + OP_PUBKEY = 254 // bitcoind internal, for completeness + OP_INVALIDOPCODE = 255 // bitcoind internal, for completeness +) + +// conditional execution constants +const ( + OpCondFalse = 0 + OpCondTrue = 1 + OpCondSkip = 2 +) + +// Some of the functions in opcodemap call things that themselves then will +// reference the opcodemap to make decisions (things like op_checksig which +// needs to parse scripts to remove opcodes, for example). +// The go compiler is very conservative in this matter and will think there +// is an initialisation loop. In order to work around this we have the fake +// ``prevariable'' opcodemapPreinit and then set the real variable to the +// preinit in init() +var opcodemap map[byte]*opcode + +func init() { + opcodemap = opcodemapPreinit +} + +var opcodemapPreinit = map[byte]*opcode{ + OP_FALSE: {value: OP_FALSE, name: "OP_0", length: 1, + opfunc: opcodeFalse}, + OP_DATA_1: {value: OP_DATA_1, name: "OP_DATA_1", length: 2, + opfunc: opcodePushData}, + OP_DATA_2: {value: OP_DATA_2, name: "OP_DATA_2", length: 3, + opfunc: opcodePushData}, + OP_DATA_3: {value: OP_DATA_3, name: "OP_DATA_3", length: 4, + opfunc: opcodePushData}, + OP_DATA_4: {value: OP_DATA_4, name: "OP_DATA_4", length: 5, + opfunc: opcodePushData}, + OP_DATA_5: {value: OP_DATA_5, name: "OP_DATA_5", length: 6, + opfunc: opcodePushData}, + OP_DATA_6: {value: OP_DATA_6, name: "OP_DATA_6", length: 7, + opfunc: opcodePushData}, + OP_DATA_7: {value: OP_DATA_7, name: "OP_DATA_7", length: 8, + opfunc: opcodePushData}, + OP_DATA_8: {value: OP_DATA_8, name: "OP_DATA_8", length: 9, + opfunc: opcodePushData}, + OP_DATA_9: {value: OP_DATA_9, name: "OP_DATA_9", length: 10, + opfunc: opcodePushData}, + OP_DATA_10: {value: OP_DATA_10, name: "OP_DATA_10", length: 11, + opfunc: opcodePushData}, + OP_DATA_11: {value: OP_DATA_11, name: "OP_DATA_11", length: 12, + opfunc: opcodePushData}, + OP_DATA_12: {value: OP_DATA_12, name: "OP_DATA_12", length: 13, + opfunc: opcodePushData}, + OP_DATA_13: {value: OP_DATA_13, name: "OP_DATA_13", length: 14, + opfunc: opcodePushData}, + OP_DATA_14: {value: OP_DATA_14, name: "OP_DATA_14", length: 15, + opfunc: opcodePushData}, + OP_DATA_15: {value: OP_DATA_15, name: "OP_DATA_15", length: 16, + opfunc: opcodePushData}, + OP_DATA_16: {value: OP_DATA_16, name: "OP_DATA_16", length: 17, + opfunc: opcodePushData}, + OP_DATA_17: {value: OP_DATA_17, name: "OP_DATA_17", length: 18, + opfunc: opcodePushData}, + OP_DATA_18: {value: OP_DATA_18, name: "OP_DATA_18", length: 19, + opfunc: opcodePushData}, + OP_DATA_19: {value: OP_DATA_19, name: "OP_DATA_19", length: 20, + opfunc: opcodePushData}, + OP_DATA_20: {value: OP_DATA_20, name: "OP_DATA_20", length: 21, + opfunc: opcodePushData}, + OP_DATA_21: {value: OP_DATA_21, name: "OP_DATA_21", length: 22, + opfunc: opcodePushData}, + OP_DATA_22: {value: OP_DATA_22, name: "OP_DATA_22", length: 23, + opfunc: opcodePushData}, + OP_DATA_23: {value: OP_DATA_23, name: "OP_DATA_23", length: 24, + opfunc: opcodePushData}, + OP_DATA_24: {value: OP_DATA_24, name: "OP_DATA_24", length: 25, + opfunc: opcodePushData}, + OP_DATA_25: {value: OP_DATA_25, name: "OP_DATA_25", length: 26, + opfunc: opcodePushData}, + OP_DATA_26: {value: OP_DATA_26, name: "OP_DATA_26", length: 27, + opfunc: opcodePushData}, + OP_DATA_27: {value: OP_DATA_27, name: "OP_DATA_27", length: 28, + opfunc: opcodePushData}, + OP_DATA_28: {value: OP_DATA_28, name: "OP_DATA_28", length: 29, + opfunc: opcodePushData}, + OP_DATA_29: {value: OP_DATA_29, name: "OP_DATA_29", length: 30, + opfunc: opcodePushData}, + OP_DATA_30: {value: OP_DATA_30, name: "OP_DATA_30", length: 31, + opfunc: opcodePushData}, + OP_DATA_31: {value: OP_DATA_31, name: "OP_DATA_31", length: 32, + opfunc: opcodePushData}, + OP_DATA_32: {value: OP_DATA_32, name: "OP_DATA_32", length: 33, + opfunc: opcodePushData}, + OP_DATA_33: {value: OP_DATA_33, name: "OP_DATA_33", length: 34, + opfunc: opcodePushData}, + OP_DATA_34: {value: OP_DATA_34, name: "OP_DATA_34", length: 35, + opfunc: opcodePushData}, + OP_DATA_35: {value: OP_DATA_35, name: "OP_DATA_35", length: 36, + opfunc: opcodePushData}, + OP_DATA_36: {value: OP_DATA_36, name: "OP_DATA_36", length: 37, + opfunc: opcodePushData}, + OP_DATA_37: {value: OP_DATA_37, name: "OP_DATA_37", length: 38, + opfunc: opcodePushData}, + OP_DATA_38: {value: OP_DATA_38, name: "OP_DATA_38", length: 39, + opfunc: opcodePushData}, + OP_DATA_39: {value: OP_DATA_39, name: "OP_DATA_39", length: 40, + opfunc: opcodePushData}, + OP_DATA_40: {value: OP_DATA_40, name: "OP_DATA_40", length: 41, + opfunc: opcodePushData}, + OP_DATA_41: {value: OP_DATA_41, name: "OP_DATA_41", length: 42, + opfunc: opcodePushData}, + OP_DATA_42: {value: OP_DATA_42, name: "OP_DATA_42", length: 43, + opfunc: opcodePushData}, + OP_DATA_43: {value: OP_DATA_43, name: "OP_DATA_43", length: 44, + opfunc: opcodePushData}, + OP_DATA_44: {value: OP_DATA_44, name: "OP_DATA_44", length: 45, + opfunc: opcodePushData}, + OP_DATA_45: {value: OP_DATA_45, name: "OP_DATA_45", length: 46, + opfunc: opcodePushData}, + OP_DATA_46: {value: OP_DATA_46, name: "OP_DATA_46", length: 47, + opfunc: opcodePushData}, + OP_DATA_47: {value: OP_DATA_47, name: "OP_DATA_47", length: 48, + opfunc: opcodePushData}, + OP_DATA_48: {value: OP_DATA_48, name: "OP_DATA_48", length: 49, + opfunc: opcodePushData}, + OP_DATA_49: {value: OP_DATA_49, name: "OP_DATA_49", length: 50, + opfunc: opcodePushData}, + OP_DATA_50: {value: OP_DATA_50, name: "OP_DATA_50", length: 51, + opfunc: opcodePushData}, + OP_DATA_51: {value: OP_DATA_51, name: "OP_DATA_51", length: 52, + opfunc: opcodePushData}, + OP_DATA_52: {value: OP_DATA_52, name: "OP_DATA_52", length: 53, + opfunc: opcodePushData}, + OP_DATA_53: {value: OP_DATA_53, name: "OP_DATA_53", length: 54, + opfunc: opcodePushData}, + OP_DATA_54: {value: OP_DATA_54, name: "OP_DATA_54", length: 55, + opfunc: opcodePushData}, + OP_DATA_55: {value: OP_DATA_55, name: "OP_DATA_55", length: 56, + opfunc: opcodePushData}, + OP_DATA_56: {value: OP_DATA_56, name: "OP_DATA_56", length: 57, + opfunc: opcodePushData}, + OP_DATA_57: {value: OP_DATA_57, name: "OP_DATA_57", length: 58, + opfunc: opcodePushData}, + OP_DATA_58: {value: OP_DATA_58, name: "OP_DATA_58", length: 59, + opfunc: opcodePushData}, + OP_DATA_59: {value: OP_DATA_59, name: "OP_DATA_59", length: 60, + opfunc: opcodePushData}, + OP_DATA_60: {value: OP_DATA_60, name: "OP_DATA_60", length: 61, + opfunc: opcodePushData}, + OP_DATA_61: {value: OP_DATA_61, name: "OP_DATA_61", length: 62, + opfunc: opcodePushData}, + OP_DATA_62: {value: OP_DATA_62, name: "OP_DATA_62", length: 63, + opfunc: opcodePushData}, + OP_DATA_63: {value: OP_DATA_63, name: "OP_DATA_63", length: 64, + opfunc: opcodePushData}, + OP_DATA_64: {value: OP_DATA_64, name: "OP_DATA_64", length: 65, + opfunc: opcodePushData}, + OP_DATA_65: {value: OP_DATA_65, name: "OP_DATA_65", length: 66, + opfunc: opcodePushData}, + OP_DATA_66: {value: OP_DATA_66, name: "OP_DATA_66", length: 67, + opfunc: opcodePushData}, + OP_DATA_67: {value: OP_DATA_67, name: "OP_DATA_67", length: 68, + opfunc: opcodePushData}, + OP_DATA_68: {value: OP_DATA_68, name: "OP_DATA_68", length: 69, + opfunc: opcodePushData}, + OP_DATA_69: {value: OP_DATA_69, name: "OP_DATA_69", length: 70, + opfunc: opcodePushData}, + OP_DATA_70: {value: OP_DATA_70, name: "OP_DATA_70", length: 71, + opfunc: opcodePushData}, + OP_DATA_71: {value: OP_DATA_71, name: "OP_DATA_71", length: 72, + opfunc: opcodePushData}, + OP_DATA_72: {value: OP_DATA_72, name: "OP_DATA_72", length: 73, + opfunc: opcodePushData}, + OP_DATA_73: {value: OP_DATA_73, name: "OP_DATA_73", length: 74, + opfunc: opcodePushData}, + OP_DATA_74: {value: OP_DATA_74, name: "OP_DATA_74", length: 75, + opfunc: opcodePushData}, + OP_DATA_75: {value: OP_DATA_75, name: "OP_DATA_75", length: 76, + opfunc: opcodePushData}, + OP_PUSHDATA1: {value: OP_PUSHDATA1, name: "OP_PUSHDATA1", length: -1, + opfunc: opcodePushData}, + OP_PUSHDATA2: {value: OP_PUSHDATA2, name: "OP_PUSHDATA2", length: -2, + opfunc: opcodePushData}, + OP_PUSHDATA4: {value: OP_PUSHDATA4, name: "OP_PUSHDATA4", length: -4, + opfunc: opcodePushData}, + OP_1NEGATE: {value: OP_1NEGATE, name: "OP_1NEGATE", length: 1, + opfunc: opcode1Negate}, + OP_RESERVED: {value: OP_RESERVED, name: "OP_RESERVED", length: 1, + opfunc: opcodeReserved}, + OP_TRUE: {value: OP_TRUE, name: "OP_1", length: 1, + opfunc: opcodeN}, + OP_2: {value: OP_2, name: "OP_2", length: 1, + opfunc: opcodeN}, + OP_3: {value: OP_3, name: "OP_3", length: 1, + opfunc: opcodeN}, + OP_4: {value: OP_4, name: "OP_4", length: 1, + opfunc: opcodeN}, + OP_5: {value: OP_5, name: "OP_5", length: 1, + opfunc: opcodeN}, + OP_6: {value: OP_6, name: "OP_6", length: 1, + opfunc: opcodeN}, + OP_7: {value: OP_7, name: "OP_7", length: 1, + opfunc: opcodeN}, + OP_8: {value: OP_8, name: "OP_8", length: 1, + opfunc: opcodeN}, + OP_9: {value: OP_9, name: "OP_9", length: 1, + opfunc: opcodeN}, + OP_10: {value: OP_10, name: "OP_10", length: 1, + opfunc: opcodeN}, + OP_11: {value: OP_11, name: "OP_11", length: 1, + opfunc: opcodeN}, + OP_12: {value: OP_12, name: "OP_12", length: 1, + opfunc: opcodeN}, + OP_13: {value: OP_13, name: "OP_13", length: 1, + opfunc: opcodeN}, + OP_14: {value: OP_14, name: "OP_14", length: 1, + opfunc: opcodeN}, + OP_15: {value: OP_15, name: "OP_15", length: 1, + opfunc: opcodeN}, + OP_16: {value: OP_16, name: "OP_16", length: 1, + opfunc: opcodeN}, + OP_NOP: {value: OP_NOP, name: "OP_NOP", length: 1, + opfunc: opcodeNop}, + OP_VER: {value: OP_VER, name: "OP_VER", length: 1, + opfunc: opcodeReserved}, + OP_IF: {value: OP_IF, name: "OP_IF", length: 1, + opfunc: opcodeIf}, + OP_NOTIF: {value: OP_NOTIF, name: "OP_NOTIF", length: 1, + opfunc: opcodeNotIf}, + OP_VERIF: {value: OP_VERIF, name: "OP_VERIF", length: 1, + opfunc: opcodeReserved}, + OP_VERNOTIF: {value: OP_VERNOTIF, name: "OP_VERNOTIF", length: 1, + opfunc: opcodeReserved}, + OP_ELSE: {value: OP_ELSE, name: "OP_ELSE", length: 1, + opfunc: opcodeElse}, + OP_ENDIF: {value: OP_ENDIF, name: "OP_ENDIF", length: 1, + opfunc: opcodeEndif}, + OP_VERIFY: {value: OP_VERIFY, name: "OP_VERIFY", length: 1, + opfunc: opcodeVerify}, + OP_RETURN: {value: OP_RETURN, name: "OP_RETURN", length: 1, + opfunc: opcodeReturn}, + OP_TOALTSTACK: {value: OP_TOALTSTACK, name: "OP_TOALTSTACK", length: 1, + opfunc: opcodeToAltStack}, + OP_FROMALTSTACK: {value: OP_FROMALTSTACK, name: "OP_FROMALTSTACK", length: 1, + opfunc: opcodeFromAltStack}, + OP_2DROP: {value: OP_2DROP, name: "OP_2DROP", length: 1, + opfunc: opcode2Drop}, + OP_2DUP: {value: OP_2DUP, name: "OP_2DUP", length: 1, + opfunc: opcode2Dup}, + OP_3DUP: {value: OP_3DUP, name: "OP_3DUP", length: 1, + opfunc: opcode3Dup}, + OP_2OVER: {value: OP_2OVER, name: "OP_2OVER", length: 1, + opfunc: opcode2Over}, + OP_2ROT: {value: OP_2ROT, name: "OP_2ROT", length: 1, + opfunc: opcode2Rot}, + OP_2SWAP: {value: OP_2SWAP, name: "OP_2SWAP", length: 1, + opfunc: opcode2Swap}, + OP_IFDUP: {value: OP_IFDUP, name: "OP_IFDUP", length: 1, + opfunc: opcodeIfDup}, + OP_DEPTH: {value: OP_DEPTH, name: "OP_DEPTH", length: 1, + opfunc: opcodeDepth}, + OP_DROP: {value: OP_DROP, name: "OP_DROP", length: 1, + opfunc: opcodeDrop}, + OP_DUP: {value: OP_DUP, name: "OP_DUP", length: 1, + opfunc: opcodeDup}, + OP_NIP: {value: OP_NIP, name: "OP_NIP", length: 1, + opfunc: opcodeNip}, + OP_OVER: {value: OP_OVER, name: "OP_OVER", length: 1, + opfunc: opcodeOver}, + OP_PICK: {value: OP_PICK, name: "OP_PICK", length: 1, + opfunc: opcodePick}, + OP_ROLL: {value: OP_ROLL, name: "OP_ROLL", length: 1, + opfunc: opcodeRoll}, + OP_ROT: {value: OP_ROT, name: "OP_ROT", length: 1, + opfunc: opcodeRot}, + OP_SWAP: {value: OP_SWAP, name: "OP_SWAP", length: 1, + opfunc: opcodeSwap}, + OP_TUCK: {value: OP_TUCK, name: "OP_TUCK", length: 1, + opfunc: opcodeTuck}, + OP_CAT: {value: OP_CAT, name: "OP_CAT", length: 1, + opfunc: opcodeDisabled}, + OP_SUBSTR: {value: OP_SUBSTR, name: "OP_SUBSTR", length: 1, + opfunc: opcodeDisabled}, + OP_LEFT: {value: OP_LEFT, name: "OP_LEFT", length: 1, + opfunc: opcodeDisabled}, + OP_RIGHT: {value: OP_RIGHT, name: "OP_RIGHT", length: 1, + opfunc: opcodeDisabled}, + OP_SIZE: {value: OP_SIZE, name: "OP_SIZE", length: 1, + opfunc: opcodeSize}, + OP_INVERT: {value: OP_INVERT, name: "OP_INVERT", length: 1, + opfunc: opcodeDisabled}, + OP_AND: {value: OP_AND, name: "OP_AND", length: 1, + opfunc: opcodeDisabled}, + OP_OR: {value: OP_OR, name: "OP_OR", length: 1, + opfunc: opcodeDisabled}, + OP_XOR: {value: OP_XOR, name: "OP_XOR", length: 1, + opfunc: opcodeDisabled}, + OP_EQUAL: {value: OP_EQUAL, name: "OP_EQUAL", length: 1, + opfunc: opcodeEqual}, + OP_EQUALVERIFY: {value: OP_EQUALVERIFY, name: "OP_EQUALVERIFY", length: 1, + opfunc: opcodeEqualVerify}, + OP_RESERVED1: {value: OP_RESERVED1, name: "OP_RESERVED1", length: 1, + opfunc: opcodeReserved}, + OP_RESERVED2: {value: OP_RESERVED2, name: "OP_RESERVED2", length: 1, + opfunc: opcodeReserved}, + OP_1ADD: {value: OP_1ADD, name: "OP_1ADD", length: 1, + opfunc: opcode1Add}, + OP_1SUB: {value: OP_1SUB, name: "OP_1SUB", length: 1, + opfunc: opcode1Sub}, + OP_2MUL: {value: OP_2MUL, name: "OP_2MUL", length: 1, + opfunc: opcodeDisabled}, + OP_2DIV: {value: OP_2DIV, name: "OP_2DIV", length: 1, + opfunc: opcodeDisabled}, + OP_NEGATE: {value: OP_NEGATE, name: "OP_NEGATE", length: 1, + opfunc: opcodeNegate}, + OP_ABS: {value: OP_ABS, name: "OP_ABS", length: 1, + opfunc: opcodeAbs}, + OP_NOT: {value: OP_NOT, name: "OP_NOT", length: 1, + opfunc: opcodeNot}, + OP_0NOTEQUAL: {value: OP_0NOTEQUAL, name: "OP_0NOTEQUAL", length: 1, + opfunc: opcode0NotEqual}, + OP_ADD: {value: OP_ADD, name: "OP_ADD", length: 1, + opfunc: opcodeAdd}, + OP_SUB: {value: OP_SUB, name: "OP_SUB", length: 1, + opfunc: opcodeSub}, + OP_MUL: {value: OP_MUL, name: "OP_MUL", length: 1, + opfunc: opcodeDisabled}, + OP_DIV: {value: OP_DIV, name: "OP_DIV", length: 1, + opfunc: opcodeDisabled}, + OP_MOD: {value: OP_MOD, name: "OP_MOD", length: 1, + opfunc: opcodeDisabled}, + OP_LSHIFT: {value: OP_LSHIFT, name: "OP_LSHIFT", length: 1, + opfunc: opcodeDisabled}, + OP_RSHIFT: {value: OP_RSHIFT, name: "OP_RSHIFT", length: 1, + opfunc: opcodeDisabled}, + OP_BOOLAND: {value: OP_BOOLAND, name: "OP_BOOLAND", length: 1, + opfunc: opcodeBoolAnd}, + OP_BOOLOR: {value: OP_BOOLOR, name: "OP_BOOLOR", length: 1, + opfunc: opcodeBoolOr}, + OP_NUMEQUAL: {value: OP_NUMEQUAL, name: "OP_NUMEQUAL", length: 1, + opfunc: opcodeNumEqual}, + OP_NUMEQUALVERIFY: {value: OP_NUMEQUALVERIFY, name: "OP_NUMEQUALVERIFY", length: 1, + opfunc: opcodeNumEqualVerify}, + OP_NUMNOTEQUAL: {value: OP_NUMNOTEQUAL, name: "OP_NUMNOTEQUAL", length: 1, + opfunc: opcodeNumNotEqual}, + OP_LESSTHAN: {value: OP_LESSTHAN, name: "OP_LESSTHAN", length: 1, + opfunc: opcodeLessThan}, + OP_GREATERTHAN: {value: OP_GREATERTHAN, name: "OP_GREATERTHAN", length: 1, + opfunc: opcodeGreaterThan}, + OP_LESSTHANOREQUAL: {value: OP_LESSTHANOREQUAL, name: "OP_LESSTHANOREQUAL", length: 1, + opfunc: opcodeLessThanOrEqual}, + OP_GREATERTHANOREQUAL: {value: OP_GREATERTHANOREQUAL, name: "OP_GREATERTHANOREQUAL", length: 1, + opfunc: opcodeGreaterThanOrEqual}, + OP_MIN: {value: OP_MIN, name: "OP_MIN", length: 1, + opfunc: opcodeMin}, + OP_MAX: {value: OP_MAX, name: "OP_MAX", length: 1, + opfunc: opcodeMax}, + OP_WITHIN: {value: OP_WITHIN, name: "OP_WITHIN", length: 1, + opfunc: opcodeWithin}, + OP_RIPEMD160: {value: OP_RIPEMD160, name: "OP_RIPEMD160", length: 1, + opfunc: opcodeRipemd160}, + OP_SHA1: {value: OP_SHA1, name: "OP_SHA1", length: 1, + opfunc: opcodeSha1}, + OP_SHA256: {value: OP_SHA256, name: "OP_SHA256", length: 1, + opfunc: opcodeSha256}, + OP_HASH160: {value: OP_HASH160, name: "OP_HASH160", length: 1, + opfunc: opcodeHash160}, + OP_HASH256: {value: OP_HASH256, name: "OP_HASH256", length: 1, + opfunc: opcodeHash256}, + OP_CODESEPARATOR: {value: OP_CODESEPARATOR, name: "OP_CODESEPARATOR", length: 1, + opfunc: opcodeCodeSeparator}, + OP_CHECKSIG: {value: OP_CHECKSIG, name: "OP_CHECKSIG", length: 1, + opfunc: opcodeCheckSig}, + OP_CHECKSIGVERIFY: {value: OP_CHECKSIGVERIFY, name: "OP_CHECKSIGVERIFY", length: 1, + opfunc: opcodeCheckSigVerify}, + OP_CHECK_MULTISIG: {value: OP_CHECK_MULTISIG, name: "OP_CHECK_MULTISIG", length: 1, + opfunc: opcodeCheckMultiSig}, + OP_CHECKMULTISIGVERIFY: {value: OP_CHECKMULTISIGVERIFY, name: "OP_CHECKMULTISIGVERIFY", length: 1, + + opfunc: opcodeCheckMultiSigVerify}, + OP_NOP1: {value: OP_NOP1, name: "OP_NOP1", length: 1, + opfunc: opcodeNop}, + OP_NOP2: {value: OP_NOP2, name: "OP_NOP2", length: 1, + opfunc: opcodeNop}, + OP_NOP3: {value: OP_NOP3, name: "OP_NOP3", length: 1, + opfunc: opcodeNop}, + OP_NOP4: {value: OP_NOP4, name: "OP_NOP4", length: 1, + opfunc: opcodeNop}, + OP_NOP5: {value: OP_NOP5, name: "OP_NOP5", length: 1, + opfunc: opcodeNop}, + OP_NOP6: {value: OP_NOP6, name: "OP_NOP6", length: 1, + opfunc: opcodeNop}, + OP_NOP7: {value: OP_NOP7, name: "OP_NOP7", length: 1, + opfunc: opcodeNop}, + OP_NOP8: {value: OP_NOP8, name: "OP_NOP8", length: 1, + opfunc: opcodeNop}, + OP_NOP9: {value: OP_NOP9, name: "OP_NOP9", length: 1, + opfunc: opcodeNop}, + OP_NOP10: {value: OP_NOP10, name: "OP_NOP10", length: 1, + opfunc: opcodeNop}, + OP_PUBKEYHASH: {value: OP_PUBKEYHASH, name: "OP_PUBKEYHASH", length: 1, + opfunc: opcodeInvalid}, + OP_PUBKEY: {value: OP_PUBKEY, name: "OP_PUBKEY", length: 1, + opfunc: opcodeInvalid}, + OP_INVALIDOPCODE: {value: OP_INVALIDOPCODE, name: "OP_INVALIDOPCODE", length: 1, + opfunc: opcodeInvalid}, +} + +type parsedOpcode struct { + opcode *opcode + data []byte + opfunc func(op parsedOpcode, s Script) error +} + +func (pop *parsedOpcode) conditional() bool { + switch pop.opcode.value { + case OP_IF: + return true + case OP_NOTIF: + return true + case OP_ELSE: + return true + case OP_ENDIF: + return true + default: + return false + } +} + +func (pop *parsedOpcode) exec(s *Script) error { + // *sigh* bitcoind pretty much mandates that we violate layering here. + // Any opcode that isn't just adding data to the stack counts here + // as an operation. + if pop.opcode.value < OP_16 { + s.numOps++ + if s.numOps > MaxOpsPerScript { + return StackErrTooManyOperations + } + + } + return pop.opcode.opfunc(pop, s) +} + +func (pop *parsedOpcode) print(oneline bool) string { + retString := pop.opcode.name + if pop.opcode.length == 1 { + return retString + } + if oneline { + retString = "" + } + if !oneline && pop.opcode.length < 0 { + //add length to the end of retString + retString += fmt.Sprintf(" 0x%0*x", 2*-pop.opcode.length, + len(pop.data)) + } + for _, val := range pop.data { + if !oneline { + retString += " " + } + retString += fmt.Sprintf("%02x", val) + } + return retString +} + +func (pop *parsedOpcode) bytes() []byte { + retbytes := []byte{pop.opcode.value} + if pop.opcode.length == 1 { + return retbytes + } + if pop.opcode.length < 0 { + l := len(pop.data) + // tempting just to hardcode to avoid the complexity here. + switch pop.opcode.length { + case -1: + retbytes = append(retbytes, byte(l)) + case -2: + retbytes = append(retbytes, byte(l&0xff), + byte(l>>8&0xff)) + case -4: + retbytes = append(retbytes, byte(l&0xff), + byte((l>>8)&0xff), byte((l>>16)&0xff), + byte((l>>24)&0xff)) + } + } + + for i := range pop.data { + retbytes = append(retbytes, pop.data[i]) + } + + return retbytes +} + +// opcode implementation functions from here + +func opcodeDisabled(op *parsedOpcode, s *Script) error { + return StackErrOpDisabled +} + +func opcodeReserved(op *parsedOpcode, s *Script) error { + return StackErrReservedOpcode +} + +// Recognised opcode, but for bitcoind internal use only. +func opcodeInvalid(op *parsedOpcode, s *Script) error { + return StackErrInvalidOpcode +} + +func opcodeFalse(op *parsedOpcode, s *Script) error { + s.dstack.PushByteArray([]byte("")) + + return nil +} + +func opcodePushData(op *parsedOpcode, s *Script) error { + s.dstack.PushByteArray(op.data) + return nil +} + +func opcode1Negate(op *parsedOpcode, s *Script) error { + s.dstack.PushInt(big.NewInt(-1)) + return nil +} + +func opcodeN(op *parsedOpcode, s *Script) error { + // 16 consecutive opcodes add increasing numbers to the stack. + s.dstack.PushInt(big.NewInt(int64(op.opcode.value - (OP_1 - 1)))) + return nil +} + +func opcodeNop(op *parsedOpcode, s *Script) error { + // This page left intentionally blank + return nil +} + +// opcodeIf computes true/false based on the value on the stack and pushes +// the condition on the condStack (conditional execution stack) +func opcodeIf(op *parsedOpcode, s *Script) error { + // opcodeIf will be executed even if it is on the non-execute side + // of the conditional, this is so proper nesting is maintained + var condval int + if s.condStack[0] == OpCondTrue { + ok, err := s.dstack.PopBool() + if err != nil { + return err + } + if ok { + condval = OpCondTrue + } + } else { + condval = OpCondSkip + } + cond := []int{condval} + // push condition to the 'head' of the slice + s.condStack = append(cond, s.condStack...) + // TODO(drahn) check if a maximum condtitional stack limit exists + return nil +} + +// opcodeNotIf computes true/false based on the value on the stack and pushes +// the (inverted) condition on the condStack (conditional execution stack) +func opcodeNotIf(op *parsedOpcode, s *Script) error { + // opcodeIf will be executed even if it is on the non-execute side + // of the conditional, this is so proper nesting is maintained + var condval int + if s.condStack[0] == OpCondTrue { + ok, err := s.dstack.PopBool() + if err != nil { + return err + } + if !ok { + condval = OpCondTrue + } + } else { + condval = OpCondSkip + } + cond := []int{condval} + // push condition to the 'head' of the slice + s.condStack = append(cond, s.condStack...) + // TODO(drahn) check if a maximum condtitional stack limit exists + return nil +} + +// opcodeElse inverts conditional execution for other half of if/else/endif +func opcodeElse(op *parsedOpcode, s *Script) error { + if len(s.condStack) < 2 { + // intial true cannot be toggled, only pushed conditionals + return StackErrNoIf + } + + switch s.condStack[0] { + case OpCondTrue: + s.condStack[0] = OpCondFalse + case OpCondFalse: + s.condStack[0] = OpCondTrue + case OpCondSkip: + // value doesn't change in skip + } + return nil +} + +// opcodeEndif terminates a conditional block, removing the value from the +// conditional execution stack. +func opcodeEndif(op *parsedOpcode, s *Script) error { + if len(s.condStack) < 2 { + // intial true cannot be popped, only pushed conditionals + return StackErrNoIf + } + + s.condStack = s.condStack[1:] + return nil +} + +func opcodeVerify(op *parsedOpcode, s *Script) error { + verified, err := s.dstack.PopBool() + if err != nil { + return err + } + + if verified != true { + return StackErrVerifyFailed + } + return nil +} + +func opcodeReturn(op *parsedOpcode, s *Script) error { + return StackErrEarlyReturn +} + +func opcodeToAltStack(op *parsedOpcode, s *Script) error { + so, err := s.dstack.PopByteArray() + if err != nil { + return err + } + s.astack.PushByteArray(so) + + return nil +} + +func opcodeFromAltStack(op *parsedOpcode, s *Script) error { + so, err := s.astack.PopByteArray() + if err != nil { + return err + } + s.dstack.PushByteArray(so) + + return nil +} + +func opcode2Drop(op *parsedOpcode, s *Script) error { + return s.dstack.DropN(2) +} + +func opcode2Dup(op *parsedOpcode, s *Script) error { + return s.dstack.DupN(2) +} + +func opcode3Dup(op *parsedOpcode, s *Script) error { + return s.dstack.DupN(3) +} + +func opcode2Over(op *parsedOpcode, s *Script) error { + return s.dstack.OverN(2) +} + +func opcode2Rot(op *parsedOpcode, s *Script) error { + return s.dstack.RotN(2) +} + +func opcode2Swap(op *parsedOpcode, s *Script) error { + return s.dstack.SwapN(2) +} + +func opcodeIfDup(op *parsedOpcode, s *Script) error { + val, err := s.dstack.PeekInt(0) + if err != nil { + return err + } + + // Push copy of data iff it isn't zero + if val.Sign() != 0 { + s.dstack.PushInt(val) + } + + return nil +} + +func opcodeDepth(op *parsedOpcode, s *Script) error { + s.dstack.PushInt(big.NewInt(int64(s.dstack.Depth()))) + return nil +} + +func opcodeDrop(op *parsedOpcode, s *Script) error { + return s.dstack.DropN(1) +} + +func opcodeDup(op *parsedOpcode, s *Script) error { + return s.dstack.DupN(1) +} + +func opcodeNip(op *parsedOpcode, s *Script) error { + return s.dstack.NipN(1) +} + +func opcodeOver(op *parsedOpcode, s *Script) error { + return s.dstack.OverN(1) +} + +// Copy object N items back in the stack to the top. Where N is the value in +// the top of the stack. +func opcodePick(op *parsedOpcode, s *Script) error { + pidx, err := s.dstack.PopInt() + if err != nil { + return err + } + + if pidx.BitLen() > 32 { + return StackErrNumberTooBig + } + + val := int(pidx.Int64()) + + return s.dstack.PickN(val) +} + +// Move object N items back in the stack to the top. Where N is the value in +// the top of the stack. +func opcodeRoll(op *parsedOpcode, s *Script) error { + ridx, err := s.dstack.PopInt() + if err != nil { + return err + } + + if ridx.BitLen() > 32 { + return StackErrNumberTooBig + } + + val := int(ridx.Int64()) + + return s.dstack.RollN(val) +} + +// Rotate top three items on the stack to the left. +// e.g. 1,2,3 -> 2,3,1 +func opcodeRot(op *parsedOpcode, s *Script) error { + return s.dstack.RotN(1) +} + +// Swap the top two items on the stack: 1,2 -> 2,1 +func opcodeSwap(op *parsedOpcode, s *Script) error { + return s.dstack.SwapN(1) +} + +// The item at the top of the stack is copied and inserted before the +// second-to-top item. e.g.: 2,1, -> 2,1,2 +func opcodeTuck(op *parsedOpcode, s *Script) error { + return s.dstack.Tuck() +} + +// Push the size of the item on top of the stack onto the stack. +func opcodeSize(op *parsedOpcode, s *Script) error { + i, err := s.dstack.PeekByteArray(0) + if err != nil { + return err + } + + s.dstack.PushInt(big.NewInt(int64(len(i)))) + return nil +} + +func opcodeEqual(op *parsedOpcode, s *Script) error { + a, err := s.dstack.PopByteArray() + if err != nil { + return err + } + b, err := s.dstack.PopByteArray() + if err != nil { + return err + } + + s.dstack.PushBool(bytes.Equal(a, b)) + return nil +} + +func opcodeEqualVerify(op *parsedOpcode, s *Script) error { + err := opcodeEqual(op, s) + if err == nil { + err = opcodeVerify(op, s) + } + return err +} + +func opcode1Add(op *parsedOpcode, s *Script) error { + m, err := s.dstack.PopInt() + if err != nil { + return err + } + + s.dstack.PushInt(new(big.Int).Add(m, big.NewInt(1))) + + return nil +} + +func opcode1Sub(op *parsedOpcode, s *Script) error { + m, err := s.dstack.PopInt() + if err != nil { + return err + } + s.dstack.PushInt(new(big.Int).Sub(m, big.NewInt(1))) + + return nil +} + +func opcodeNegate(op *parsedOpcode, s *Script) error { + // XXX when we remove types just flip the 0x80 bit of msb + m, err := s.dstack.PopInt() + if err != nil { + return err + } + + s.dstack.PushInt(new(big.Int).Neg(m)) + return nil +} + +func opcodeAbs(op *parsedOpcode, s *Script) error { + // XXX when we remove types just &= ~0x80 on msb + m, err := s.dstack.PopInt() + if err != nil { + return err + } + + s.dstack.PushInt(new(big.Int).Abs(m)) + + return nil +} + +// If then input is 0 or 1, it is flipped. Otherwise the output will be 0. +// (n.b. official client just has 1 is 0, else 0) +func opcodeNot(op *parsedOpcode, s *Script) error { + m, err := s.dstack.PopInt() + if err != nil { + return err + } + if m.Sign() == 0 { + s.dstack.PushInt(big.NewInt(1)) + } else { + s.dstack.PushInt(big.NewInt(0)) + } + return nil +} + +// opcode returns 0 if the input is 0, 1 otherwise. +func opcode0NotEqual(op *parsedOpcode, s *Script) error { + m, err := s.dstack.PopInt() + if err != nil { + return err + } + if m.Sign() != 0 { + m.SetInt64(1) + } + s.dstack.PushInt(m) + + return nil +} + +// Push result of adding top two entries on stack +func opcodeAdd(op *parsedOpcode, s *Script) error { + v0, err := s.dstack.PopInt() + if err != nil { + return err + } + + v1, err := s.dstack.PopInt() + if err != nil { + return err + } + + s.dstack.PushInt(new(big.Int).Add(v0, v1)) + return nil +} + +// Push result of subtracting 2nd entry on stack from first. +func opcodeSub(op *parsedOpcode, s *Script) error { + v0, err := s.dstack.PopInt() + if err != nil { + return err + } + + v1, err := s.dstack.PopInt() + if err != nil { + return err + } + + s.dstack.PushInt(new(big.Int).Sub(v1, v0)) + return nil +} + +// If both of the top two entries on the stack are not zero output is 1. +// Otherwise, 0. +func opcodeBoolAnd(op *parsedOpcode, s *Script) error { + v0, err := s.dstack.PopInt() + if err != nil { + return err + } + + v1, err := s.dstack.PopInt() + if err != nil { + return err + } + + if v0.Sign() != 0 && v1.Sign() != 0 { + s.dstack.PushInt(big.NewInt(1)) + } else { + s.dstack.PushInt(big.NewInt(0)) + } + + return nil +} + +// If either of the top two entries on the stack are not zero output is 1. +// Otherwise, 0. +func opcodeBoolOr(op *parsedOpcode, s *Script) error { + v0, err := s.dstack.PopInt() + if err != nil { + return err + } + + v1, err := s.dstack.PopInt() + if err != nil { + return err + } + + if v0.Sign() != 0 || v1.Sign() != 0 { + s.dstack.PushInt(big.NewInt(1)) + } else { + s.dstack.PushInt(big.NewInt(0)) + } + + return nil +} + +func opcodeNumEqual(op *parsedOpcode, s *Script) error { + v0, err := s.dstack.PopInt() + if err != nil { + return err + } + + v1, err := s.dstack.PopInt() + if err != nil { + return err + } + + if v0.Cmp(v1) == 0 { + s.dstack.PushInt(big.NewInt(1)) + } else { + s.dstack.PushInt(big.NewInt(0)) + } + + return nil +} + +func opcodeNumEqualVerify(op *parsedOpcode, s *Script) error { + err := opcodeNumEqual(op, s) + if err == nil { + err = opcodeVerify(op, s) + } + return err +} + +func opcodeNumNotEqual(op *parsedOpcode, s *Script) error { + v0, err := s.dstack.PopInt() + if err != nil { + return err + } + + v1, err := s.dstack.PopInt() + if err != nil { + return err + } + + if v0.Cmp(v1) != 0 { + s.dstack.PushInt(big.NewInt(1)) + } else { + s.dstack.PushInt(big.NewInt(0)) + } + + return nil +} + +func opcodeLessThan(op *parsedOpcode, s *Script) error { + v0, err := s.dstack.PopInt() + if err != nil { + return err + } + + v1, err := s.dstack.PopInt() + if err != nil { + return err + } + + if v1.Cmp(v0) == -1 { + s.dstack.PushInt(big.NewInt(1)) + } else { + s.dstack.PushInt(big.NewInt(0)) + } + + return nil +} + +func opcodeGreaterThan(op *parsedOpcode, s *Script) error { + v0, err := s.dstack.PopInt() + if err != nil { + return err + } + + v1, err := s.dstack.PopInt() + if err != nil { + return err + } + + if v1.Cmp(v0) == 1 { + s.dstack.PushInt(big.NewInt(1)) + } else { + s.dstack.PushInt(big.NewInt(0)) + } + return nil +} + +func opcodeLessThanOrEqual(op *parsedOpcode, s *Script) error { + v0, err := s.dstack.PopInt() + if err != nil { + return err + } + + v1, err := s.dstack.PopInt() + if err != nil { + return err + } + + if v1.Cmp(v0) <= 0 { + s.dstack.PushInt(big.NewInt(1)) + } else { + s.dstack.PushInt(big.NewInt(0)) + } + return nil +} + +func opcodeGreaterThanOrEqual(op *parsedOpcode, s *Script) error { + v0, err := s.dstack.PopInt() + if err != nil { + return err + } + + v1, err := s.dstack.PopInt() + if err != nil { + return err + } + + if v1.Cmp(v0) >= 0 { + s.dstack.PushInt(big.NewInt(1)) + } else { + s.dstack.PushInt(big.NewInt(0)) + } + + return nil +} + +func opcodeMin(op *parsedOpcode, s *Script) error { + v0, err := s.dstack.PopInt() + if err != nil { + return err + } + + v1, err := s.dstack.PopInt() + if err != nil { + return err + } + + if v1.Cmp(v0) == -1 { + s.dstack.PushInt(new(big.Int).Set(v1)) + } else { + s.dstack.PushInt(new(big.Int).Set(v0)) + } + + return nil +} + +func opcodeMax(op *parsedOpcode, s *Script) error { + v0, err := s.dstack.PopInt() + if err != nil { + return err + } + + v1, err := s.dstack.PopInt() + if err != nil { + return err + } + + if v1.Cmp(v0) == 1 { + s.dstack.PushInt(new(big.Int).Set(v1)) + } else { + s.dstack.PushInt(new(big.Int).Set(v0)) + } + + return nil +} + +// stack input: x, min, max. Returns 1 if x is within specified range +// (left inclusive), 0 otherwise +func opcodeWithin(op *parsedOpcode, s *Script) error { + maxVal, err := s.dstack.PopInt() + if err != nil { + return err + } + + minVal, err := s.dstack.PopInt() + if err != nil { + return err + } + + x, err := s.dstack.PopInt() + if err != nil { + return err + } + + if x.Cmp(minVal) >= 0 && x.Cmp(maxVal) == -1 { + s.dstack.PushInt(big.NewInt(1)) + } else { + s.dstack.PushInt(big.NewInt(0)) + } + return nil +} + +// Calculate the hash of hasher over buf. +func calcHash(buf []byte, hasher hash.Hash) []byte { + hasher.Write(buf) + return hasher.Sum(nil) +} + +// calculate hash160 which is ripemd160(sha256(data)) +func calcHash160(buf []byte) []byte { + return calcHash(calcHash(buf, sha256.New()), ripemd160.New()) +} + +func opcodeRipemd160(op *parsedOpcode, s *Script) error { + buf, err := s.dstack.PopByteArray() + if err != nil { + return err + } + + s.dstack.PushByteArray(calcHash(buf, ripemd160.New())) + return nil +} + +func opcodeSha1(op *parsedOpcode, s *Script) error { + buf, err := s.dstack.PopByteArray() + if err != nil { + return err + } + + s.dstack.PushByteArray(calcHash(buf, sha1.New())) + return nil +} + +func opcodeSha256(op *parsedOpcode, s *Script) error { + buf, err := s.dstack.PopByteArray() + if err != nil { + return err + } + + s.dstack.PushByteArray(calcHash(buf, sha256.New())) + return nil +} + +func opcodeHash160(op *parsedOpcode, s *Script) error { + buf, err := s.dstack.PopByteArray() + if err != nil { + return err + } + + s.dstack.PushByteArray(calcHash160(buf)) + return nil +} + +func opcodeHash256(op *parsedOpcode, s *Script) error { + buf, err := s.dstack.PopByteArray() + if err != nil { + return err + } + + s.dstack.PushByteArray(btcwire.DoubleSha256(buf)) + return nil +} + +func opcodeCodeSeparator(op *parsedOpcode, s *Script) error { + s.lastcodesep = s.scriptoff + + return nil +} + +func opcodeCheckSig(op *parsedOpcode, s *Script) error { + + pkStr, err := s.dstack.PopByteArray() + if err != nil { + return err + } + + sigStr, err := s.dstack.PopByteArray() + if err != nil { + return err + } + + // Trim off hashtype from the signature string. + hashType := sigStr[len(sigStr)-1] + sigStr = sigStr[:len(sigStr)-1] + + // Get script from the last OP_CODESEPARATOR and without any subsequent + // OP_CODESEPARATORs + subScript := s.subScript() + + // Unlikely to hit any cases here, but remove the signature from + // the script if present. + subScript = removeOpcodeByData(subScript, sigStr) + + hash := s.calcScriptHash(subScript, hashType) + + pubKey, err := btcec.ParsePubKey(pkStr, btcec.S256()) + if err != nil { + log.Warnf("can't parse public key from string: %v", err) + return err + } + + signature, err := btcec.ParseSignature(sigStr, btcec.S256()) + if err != nil { + log.Warnf("can't parse signature from string: %v", err) + return err + } + + log.Tracef("%v", newLogClosure(func() string { + return fmt.Sprintf("op_checksig pubKey %v\npk.x: %v\n "+ + "pk.y: %v\n r: %v\n s: %v\ncheckScriptHash %v", + spew.Sdump(pkStr), pubKey.X, pubKey.Y, + signature.R, signature.S, spew.Sdump(hash)) + })) + ok := ecdsa.Verify(pubKey, hash, signature.R, signature.S) + if !ok { + log.Warnf("ecdsa.Verify valid: %v", ok) + } + + s.dstack.PushBool(ok) + return nil +} + +func opcodeCheckSigVerify(op *parsedOpcode, s *Script) error { + err := opcodeCheckSig(op, s) + if err == nil { + err = opcodeVerify(op, s) + } + return err +} + +// stack; sigs pubkeys +func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error { + + numPubkeys, err := s.dstack.PopInt() + if err != nil { + return err + } + + // XXX arbitrary limits + // nore more than 20 pubkeyhs, or 201 operations + + if numPubkeys.BitLen() > 32 { + return StackErrNumberTooBig + } + + npk := int(numPubkeys.Int64()) + if npk < 0 || npk > MaxPubKeysPerMultiSig { + return StackErrTooManyPubkeys + } + s.numOps += npk + if s.numOps > MaxOpsPerScript { + return StackErrTooManyOperations + } + pubKeyStrings := make([][]byte, npk) + pubKeys := make([]*ecdsa.PublicKey, npk) + for i := range pubKeys { + pubKeyStrings[i], err = s.dstack.PopByteArray() + if err != nil { + return err + } + } + + numSignatures, err := s.dstack.PopInt() + if err != nil { + return err + } + if numSignatures.BitLen() > 32 { + return StackErrNumberTooBig + } + + nsig := int(numSignatures.Int64()) + + sigStrings := make([][]byte, nsig) + signatures := make([]*btcec.Signature, nsig) + for i := range signatures { + sigStrings[i], err = s.dstack.PopByteArray() + if err != nil { + return err + } + // skip off the last byte for hashtype + signatures[i], err = + btcec.ParseSignature( + sigStrings[i][:len(sigStrings[i])-1], + btcec.S256()) + if err != nil { + return err + } + } + + // bug in bitcoind mean we pop one more stack value than should be used. + _, err = s.dstack.PopByteArray() + if err != nil { + return nil + } + + // Trim OP_CODESEPARATORs + script := s.subScript() + + // Remove any of the signatures that happen to be in the script. + // can't sign somthing containing the signature you're making, after + // all + for i := range sigStrings { + script = removeOpcodeByData(script, sigStrings[i]) + } + + curPk := 0 + for i := range signatures { + // check signatures. + success := false + // get hashtype from original byte string + hashType := sigStrings[i][len(sigStrings[i])-1] + + hash := s.calcScriptHash(script, hashType) + inner: + // Find first pubkey that successfully validates signature. + // we start off the search from the key that was successful + // last time. + for ; curPk < len(pubKeys); curPk++ { + if pubKeys[curPk] == nil { + pubKeys[curPk], err = + btcec.ParsePubKey(pubKeyStrings[curPk], + btcec.S256()) + if err != nil { + continue + } + } + success = ecdsa.Verify(pubKeys[curPk], hash, + signatures[i].R, signatures[i].S) + if success { + break inner + } + } + if success == false { + s.dstack.PushBool(false) + return nil + } + } + s.dstack.PushBool(true) + + return nil +} + +func opcodeCheckMultiSigVerify(op *parsedOpcode, s *Script) error { + err := opcodeCheckMultiSig(op, s) + if err == nil { + err = opcodeVerify(op, s) + } + return err +} diff --git a/opcode_test.go b/opcode_test.go new file mode 100644 index 00000000..3970b10d --- /dev/null +++ b/opcode_test.go @@ -0,0 +1,3104 @@ +// Copyright (c) 2013 Conformal Systems LLC. +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcscript_test + +import ( + "bytes" + "fmt" + "github.com/conformal/btcscript" + "github.com/conformal/btcwire" + "github.com/conformal/seelog" + "github.com/davecgh/go-spew/spew" + "os" + "testing" +) + +// test scripts to test as many opcodes as possible. +// All run on a fake tx with a single in, single out. +type opcodeTest struct { + script []byte + shouldPass bool + shouldFail error +} + +var opcodeTests = []opcodeTest{ + // does nothing, but doesn't put a true on the stack, should fail + {script: []byte{btcscript.OP_NOP}, shouldPass: false}, + // should just put true on the stack, thus passes. + {script: []byte{btcscript.OP_TRUE}, shouldPass: true}, + // should just put false on the stack, thus fails. + {script: []byte{btcscript.OP_FALSE}, shouldPass: false}, + // tests OP_VERIFY (true). true is needed since else stack is empty. + {script: []byte{btcscript.OP_TRUE, btcscript.OP_VERIFY, + btcscript.OP_TRUE}, shouldPass: true}, + // tests OP_VERIFY (false), will error out. + {script: []byte{btcscript.OP_FALSE, btcscript.OP_VERIFY, + btcscript.OP_TRUE}, shouldPass: false}, + // tests OP_VERIFY with empty stack (errors) + {script: []byte{btcscript.OP_VERIFY}, shouldPass: false}, + // test OP_RETURN immediately fails the script (empty stack) + {script: []byte{btcscript.OP_RETURN}, shouldPass: false}, + // test OP_RETURN immediately fails the script (full stack) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_RETURN}, + shouldPass: false}, + // tests numequal with a trivial example (passing) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_NUMEQUAL}, shouldPass: true}, + // tests numequal with a trivial example (failing) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_NUMEQUAL}, shouldPass: false}, + // tests numequal with insufficient arguments (1/2) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_NUMEQUAL}, + shouldPass: false}, + // tests numequal with insufficient arguments (0/2) + {script: []byte{btcscript.OP_NUMEQUAL}, shouldPass: false}, + // tests numnotequal with a trivial example (passing) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_NUMNOTEQUAL}, shouldPass: true}, + // tests numnotequal with a trivial example (failing) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_NUMNOTEQUAL}, shouldPass: false}, + // tests numnotequal with insufficient arguments (1/2) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_NUMNOTEQUAL}, + shouldPass: false}, + // tests numnotequal with insufficient arguments (0/2) + {script: []byte{btcscript.OP_NUMNOTEQUAL}, shouldPass: false}, + // test numequal_verify with a trivial example (passing) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_NUMEQUALVERIFY, btcscript.OP_TRUE}, + shouldPass: true}, + // test numequal_verify with a trivial example (failing) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_NUMEQUALVERIFY, btcscript.OP_TRUE}, + shouldPass: false}, + // test OP_1ADD by adding 1 to 0 + {script: []byte{btcscript.OP_FALSE, btcscript.OP_1ADD}, + shouldPass: true}, + // test OP_1ADD without args (should error) + {script: []byte{btcscript.OP_1ADD}, shouldPass: false}, + // test OP_1NEGATE by adding 1 to -1 + {script: []byte{btcscript.OP_1NEGATE, btcscript.OP_1ADD}, + shouldPass: false}, + // test OP_1NEGATE by adding negating -1 + {script: []byte{btcscript.OP_1NEGATE, btcscript.OP_NEGATE}, + shouldPass: true}, + // test OP_NEGATE by adding 1 to -1 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_NEGATE, + btcscript.OP_1ADD}, shouldPass: false}, + // test OP_NEGATE with no args + {script: []byte{btcscript.OP_NEGATE}, shouldPass: false}, + // test OP_1SUB -> 1 - 1 = 0 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_1SUB}, + shouldPass: false}, + // test OP_1SUB -> negate(0 -1) = 1 + {script: []byte{btcscript.OP_FALSE, btcscript.OP_1SUB, + btcscript.OP_NEGATE}, shouldPass: true}, + // test OP_1SUB with empty stack + {script: []byte{btcscript.OP_1SUB}, shouldPass: false}, + // OP_DEPTH with empty stack, means 0 on stack at end + {script: []byte{btcscript.OP_DEPTH}, shouldPass: false}, + // 1 +1 -1 = 1. tests depth + add + {script: []byte{btcscript.OP_TRUE, btcscript.OP_DEPTH, btcscript.OP_ADD, + btcscript.OP_1SUB}, shouldPass: true}, + // 1 +1 -1 = 0 . tests dept + add + {script: []byte{btcscript.OP_TRUE, btcscript.OP_DEPTH, + btcscript.OP_ADD, btcscript.OP_1SUB, btcscript.OP_1SUB}, + shouldPass: false}, + // OP_ADD with only one thing on stack should error + {script: []byte{btcscript.OP_TRUE, btcscript.OP_ADD}, + shouldPass: false}, + // OP_ADD with nothing on stack should error + {script: []byte{btcscript.OP_ADD}, shouldPass: false}, + // OP_SUB: 1-1=0 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_SUB}, shouldPass: false}, + // OP_SUB: 1+1-1=1 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_ADD, btcscript.OP_SUB}, shouldPass: true}, + // OP_SUB with only one thing on stack should error + {script: []byte{btcscript.OP_TRUE, btcscript.OP_SUB}, + shouldPass: false}, + // OP_SUB with nothing on stack should error + {script: []byte{btcscript.OP_SUB}, shouldPass: false}, + // OP_LESSTHAN 1 < 1 == false + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_LESSTHAN}, shouldPass: false}, + // OP_LESSTHAN 1 < 0 == false + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_LESSTHAN}, shouldPass: false}, + // OP_LESSTHAN 0 < 1 == true + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, + btcscript.OP_LESSTHAN}, shouldPass: true}, + // OP_LESSTHAN only one arg + {script: []byte{btcscript.OP_TRUE, btcscript.OP_LESSTHAN}, + shouldPass: false}, + // OP_LESSTHAN no args + {script: []byte{btcscript.OP_LESSTHAN}, shouldPass: false}, + + // OP_LESSTHANOREQUAL 1 <= 1 == true + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_LESSTHANOREQUAL}, shouldPass: true}, + // OP_LESSTHANOREQUAL 1 <= 0 == false + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_LESSTHANOREQUAL}, shouldPass: false}, + // OP_LESSTHANOREQUAL 0 <= 1 == true + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, + btcscript.OP_LESSTHANOREQUAL}, shouldPass: true}, + // OP_LESSTHANOREQUAL only one arg + {script: []byte{btcscript.OP_TRUE, btcscript.OP_LESSTHANOREQUAL}, + shouldPass: false}, + // OP_LESSTHANOREQUAL no args + {script: []byte{btcscript.OP_LESSTHANOREQUAL}, shouldPass: false}, + + // OP_GREATERTHAN 1 > 1 == false + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_GREATERTHAN}, shouldPass: false}, + // OP_GREATERTHAN 1 > 0 == true + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_GREATERTHAN}, shouldPass: true}, + // OP_GREATERTHAN 0 > 1 == false + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, + btcscript.OP_GREATERTHAN}, shouldPass: false}, + // OP_GREATERTHAN only one arg + {script: []byte{btcscript.OP_TRUE, btcscript.OP_GREATERTHAN}, + shouldPass: false}, + // OP_GREATERTHAN no args + {script: []byte{btcscript.OP_GREATERTHAN}, shouldPass: false}, + + // OP_GREATERTHANOREQUAL 1 >= 1 == true + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_GREATERTHANOREQUAL}, shouldPass: true}, + // OP_GREATERTHANOREQUAL 1 >= 0 == false + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_GREATERTHANOREQUAL}, shouldPass: true}, + // OP_GREATERTHANOREQUAL 0 >= 1 == true + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, + btcscript.OP_GREATERTHANOREQUAL}, shouldPass: false}, + // OP_GREATERTHANOREQUAL only one arg + {script: []byte{btcscript.OP_TRUE, btcscript.OP_GREATERTHANOREQUAL}, + shouldPass: false}, + // OP_GREATERTHANOREQUAL no args + {script: []byte{btcscript.OP_GREATERTHANOREQUAL}, shouldPass: false}, + + // OP_MIN basic functionality -> min(0,1) = 0 = min(1,0) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_MIN}, shouldPass: false}, + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, + btcscript.OP_MIN}, shouldPass: false}, + // OP_MIN -> 1 arg errors + {script: []byte{btcscript.OP_TRUE, btcscript.OP_MIN}, + shouldPass: false}, + // OP_MIN -> 0 arg errors + {script: []byte{btcscript.OP_MIN}, shouldPass: false}, + // OP_MAX basic functionality -> max(0,1) = 1 = max(1,0) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_MAX}, shouldPass: true}, + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, + btcscript.OP_MAX}, shouldPass: true}, + // OP_MAX -> 1 arg errors + {script: []byte{btcscript.OP_TRUE, btcscript.OP_MAX}, + shouldPass: false}, + // OP_MAX -> 0 arg errors + {script: []byte{btcscript.OP_MAX}, shouldPass: false}, + + // By this point we know a number of operations appear to be working + // correctly. we can use them to test the other number pushing + // operations + {script: []byte{btcscript.OP_TRUE, btcscript.OP_1ADD, btcscript.OP_2, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_2, btcscript.OP_1ADD, btcscript.OP_3, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_3, btcscript.OP_1ADD, btcscript.OP_4, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_4, btcscript.OP_1ADD, btcscript.OP_5, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_5, btcscript.OP_1ADD, btcscript.OP_6, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_6, btcscript.OP_1ADD, btcscript.OP_7, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_7, btcscript.OP_1ADD, btcscript.OP_8, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_8, btcscript.OP_1ADD, btcscript.OP_9, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_9, btcscript.OP_1ADD, btcscript.OP_10, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_10, btcscript.OP_1ADD, btcscript.OP_11, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_11, btcscript.OP_1ADD, btcscript.OP_12, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_12, btcscript.OP_1ADD, btcscript.OP_13, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_13, btcscript.OP_1ADD, btcscript.OP_14, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_14, btcscript.OP_1ADD, btcscript.OP_15, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_15, btcscript.OP_1ADD, btcscript.OP_16, + btcscript.OP_EQUAL}, shouldPass: true}, + + // Test OP_WITHIN x, min, max + // 0 <= 1 < 2 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, btcscript.OP_2, + btcscript.OP_WITHIN}, shouldPass: true}, + // 1 <= 0 < 2 FAIL + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, btcscript.OP_2, + btcscript.OP_WITHIN}, shouldPass: false}, + // 1 <= 1 < 2 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, btcscript.OP_2, + btcscript.OP_WITHIN}, shouldPass: true}, + // 1 <= 2 < 2 FAIL + {script: []byte{btcscript.OP_2, btcscript.OP_TRUE, btcscript.OP_2, + btcscript.OP_WITHIN}, shouldPass: false}, + // only two arguments + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_WITHIN}, shouldPass: false}, + // only one argument + {script: []byte{btcscript.OP_TRUE, btcscript.OP_WITHIN}, + shouldPass: false}, + // no arguments + {script: []byte{btcscript.OP_WITHIN}, shouldPass: false}, + + // OP_BOOLAND + // 1 && 1 == 1 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_BOOLAND}, shouldPass: true}, + // 1 && 0 == 0 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_BOOLAND}, shouldPass: false}, + // 0 && 1 == 0 + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, + btcscript.OP_BOOLAND}, shouldPass: false}, + // 0 && 0 == 0 + {script: []byte{btcscript.OP_FALSE, btcscript.OP_FALSE, + btcscript.OP_BOOLAND}, shouldPass: false}, + // 0 && - boom + {script: []byte{btcscript.OP_TRUE, btcscript.OP_BOOLAND}, + shouldPass: false}, + // && - boom + {script: []byte{btcscript.OP_BOOLAND}, shouldPass: false}, + + // OP_BOOLOR + // 1 || 1 == 1 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_BOOLOR}, shouldPass: true}, + // 1 || 0 == 1 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_BOOLOR}, shouldPass: true}, + // 0 || 1 == 1 + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, + btcscript.OP_BOOLOR}, shouldPass: true}, + // 0 || 0 == 0 + {script: []byte{btcscript.OP_FALSE, btcscript.OP_FALSE, + btcscript.OP_BOOLOR}, shouldPass: false}, + // 0 && - boom + {script: []byte{btcscript.OP_TRUE, btcscript.OP_BOOLOR}, + shouldPass: false}, + // && - boom + {script: []byte{btcscript.OP_BOOLOR}, shouldPass: false}, + + // OP_0NOTEQUAL + // 1 with input != 0 XXX check output is actually 1. + {script: []byte{btcscript.OP_TRUE, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_2, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_3, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_4, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_5, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_6, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_7, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_8, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_9, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_10, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_11, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_12, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_13, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_14, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_15, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_16, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_FALSE, btcscript.OP_0NOTEQUAL}, shouldPass: false}, + // No arguments also blows up + {script: []byte{btcscript.OP_0NOTEQUAL}, shouldPass: false}, + + // OP_NOT: 1 i input is 0, else 0 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_2, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_3, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_4, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_5, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_6, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_7, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_8, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_9, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_10, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_11, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_12, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_13, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_14, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_15, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_16, btcscript.OP_NOT}, shouldPass: false}, + // check negative numbers too + {script: []byte{btcscript.OP_TRUE, btcscript.OP_NEGATE, + btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_FALSE, btcscript.OP_NOT}, + shouldPass: true}, + // No arguments also blows up + {script: []byte{btcscript.OP_NOT}, shouldPass: false}, + + // Conditional Execution + {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: true}, + {script: []byte{btcscript.OP_1, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: false}, + {script: []byte{btcscript.OP_1, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: true}, + {script: []byte{btcscript.OP_0, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: false}, + {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2}, shouldFail: btcscript.StackErrMissingEndif}, + {script: []byte{btcscript.OP_1, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2}, shouldFail: btcscript.StackErrMissingEndif}, + {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_IF, btcscript.OP_IF, btcscript.OP_1, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ENDIF}, shouldPass: true}, + {script: []byte{btcscript.OP_1, btcscript.OP_IF, btcscript.OP_IF, btcscript.OP_1, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ENDIF}, shouldFail: btcscript.StackErrUnderflow}, + {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ELSE, btcscript.OP_1, btcscript.OP_ENDIF}, shouldPass: true}, + {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ELSE, btcscript.OP_1, btcscript.OP_ENDIF}, shouldPass: true}, + {script: []byte{btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ENDIF}, shouldFail: btcscript.StackErrUnderflow}, + {script: []byte{btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF}, shouldFail: btcscript.StackErrNoIf}, + {script: []byte{btcscript.OP_ENDIF}, shouldFail: btcscript.StackErrNoIf}, + /* up here because error from sig parsing is undefined. */ + {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_DATA_65, + 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, + 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, + 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, 0x71, 0x30, 0x2f, + 0xa2, 0x84, 0x14, 0xe7, 0xaa, 0xb3, 0x73, 0x97, 0xf5, 0x54, + 0xa7, 0xdf, 0x5f, 0x14, 0x2c, 0x21, 0xc1, 0xb7, 0x30, 0x3b, + 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, + 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, + btcscript.OP_1, btcscript.OP_CHECK_MULTISIG}, + shouldPass: false}, + /* up here because no defined error case. */ + {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_DATA_65, + 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, + 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, + 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, 0x71, 0x30, 0x2f, + 0xa2, 0x84, 0x14, 0xe7, 0xaa, 0xb3, 0x73, 0x97, 0xf5, 0x54, + 0xa7, 0xdf, 0x5f, 0x14, 0x2c, 0x21, 0xc1, 0xb7, 0x30, 0x3b, + 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, + 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, + btcscript.OP_1, btcscript.OP_CHECKMULTISIGVERIFY}, + shouldPass: false}, + + // Invalid Opcodes + {script: []byte{186}, shouldPass: false}, + {script: []byte{187}, shouldPass: false}, + {script: []byte{188}, shouldPass: false}, + {script: []byte{189}, shouldPass: false}, + {script: []byte{190}, shouldPass: false}, + {script: []byte{191}, shouldPass: false}, + {script: []byte{192}, shouldPass: false}, + {script: []byte{193}, shouldPass: false}, + {script: []byte{194}, shouldPass: false}, + {script: []byte{195}, shouldPass: false}, + {script: []byte{195}, shouldPass: false}, + {script: []byte{196}, shouldPass: false}, + {script: []byte{197}, shouldPass: false}, + {script: []byte{198}, shouldPass: false}, + {script: []byte{199}, shouldPass: false}, + {script: []byte{200}, shouldPass: false}, + {script: []byte{201}, shouldPass: false}, + {script: []byte{202}, shouldPass: false}, + {script: []byte{203}, shouldPass: false}, + {script: []byte{204}, shouldPass: false}, + {script: []byte{205}, shouldPass: false}, + {script: []byte{206}, shouldPass: false}, + {script: []byte{207}, shouldPass: false}, + {script: []byte{208}, shouldPass: false}, + {script: []byte{209}, shouldPass: false}, + {script: []byte{210}, shouldPass: false}, + {script: []byte{211}, shouldPass: false}, + {script: []byte{212}, shouldPass: false}, + {script: []byte{213}, shouldPass: false}, + {script: []byte{214}, shouldPass: false}, + {script: []byte{215}, shouldPass: false}, + {script: []byte{216}, shouldPass: false}, + {script: []byte{217}, shouldPass: false}, + {script: []byte{218}, shouldPass: false}, + {script: []byte{219}, shouldPass: false}, + {script: []byte{220}, shouldPass: false}, + {script: []byte{221}, shouldPass: false}, + {script: []byte{222}, shouldPass: false}, + {script: []byte{223}, shouldPass: false}, + {script: []byte{224}, shouldPass: false}, + {script: []byte{225}, shouldPass: false}, + {script: []byte{226}, shouldPass: false}, + {script: []byte{227}, shouldPass: false}, + {script: []byte{228}, shouldPass: false}, + {script: []byte{229}, shouldPass: false}, + {script: []byte{230}, shouldPass: false}, + {script: []byte{231}, shouldPass: false}, + {script: []byte{232}, shouldPass: false}, + {script: []byte{233}, shouldPass: false}, + {script: []byte{234}, shouldPass: false}, + {script: []byte{235}, shouldPass: false}, + {script: []byte{236}, shouldPass: false}, + {script: []byte{237}, shouldPass: false}, + {script: []byte{238}, shouldPass: false}, + {script: []byte{239}, shouldPass: false}, + {script: []byte{240}, shouldPass: false}, + {script: []byte{241}, shouldPass: false}, + {script: []byte{242}, shouldPass: false}, + {script: []byte{243}, shouldPass: false}, + {script: []byte{244}, shouldPass: false}, + {script: []byte{245}, shouldPass: false}, + {script: []byte{246}, shouldPass: false}, + {script: []byte{247}, shouldPass: false}, + {script: []byte{248}, shouldPass: false}, + {script: []byte{249}, shouldPass: false}, + {script: []byte{250}, shouldPass: false}, + {script: []byte{251}, shouldPass: false}, + {script: []byte{252}, shouldPass: false}, +} + +func testScript(t *testing.T, script []byte) (err error) { + // mock up fake tx. + tx := &btcwire.MsgTx{ + Version: 1, + TxIn: []*btcwire.TxIn{ + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash{}, + Index: 0xffffffff, + }, + SignatureScript: []byte{btcscript.OP_NOP}, + Sequence: 0xffffffff, + }, + }, + TxOut: []*btcwire.TxOut{ + &btcwire.TxOut{ + Value: 0x12a05f200, + PkScript: []byte{}, + }, + }, + LockTime: 0, + } + + tx.TxOut[0].PkScript = script + + engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript, + tx.TxOut[0].PkScript, 0, tx, 1, false) + if err != nil { + return err + } + return engine.Execute() +} + +func TestScripts(t *testing.T) { + log, err := seelog.LoggerFromWriterWithMinLevel(os.Stdout, + seelog.InfoLvl) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to create logger: %v", err) + return + } + defer log.Flush() + btcscript.UseLogger(log) + // for each entry in the list + for i := range opcodeTests { + shouldPass := opcodeTests[i].shouldPass + shouldFail := opcodeTests[i].shouldFail + err := testScript(t, opcodeTests[i].script) + if shouldFail != nil { + if err == nil { + t.Errorf("test %d passed should fail with %v", i, err) + } else if shouldFail != err { + t.Errorf("test %d failed with wrong error [%v], expected [%v]", i, err, shouldFail) + } + } + if shouldPass && err != nil { + t.Errorf("test %d failed: %v", i, err) + } else if !shouldPass && err == nil { + t.Errorf("test %d passed, should fail", i) + } + } +} + +// Detailed tests for opcodes, we inspect machine state before and after the +// opcode and check that it has the effect on the state that we expect. +type detailedTest struct { + name string + before [][]byte + altbefore [][]byte + script []byte + expectedReturn error + after [][]byte + altafter [][]byte + disassembly string + disassemblyerr error +} + +var detailedTests = []detailedTest{ + { + name: "noop", + before: [][]byte{{1}, {2}, {3}, {4}, {5}}, + script: []byte{btcscript.OP_NOP}, + after: [][]byte{{1}, {2}, {3}, {4}, {5}}, + disassembly: "OP_NOP", + }, + { + name: "dup", + before: [][]byte{{1}}, + script: []byte{btcscript.OP_DUP}, + after: [][]byte{{1}, {1}}, + disassembly: "OP_DUP", + }, + { + name: "dup2", + before: [][]byte{{1}, {2}}, + script: []byte{btcscript.OP_2DUP}, + after: [][]byte{{1}, {2}, {1}, {2}}, + disassembly: "OP_2DUP", + }, + { + name: "dup3", + before: [][]byte{{1}, {2}, {3}}, + script: []byte{btcscript.OP_3DUP}, + after: [][]byte{{1}, {2}, {3}, {1}, {2}, {3}}, + disassembly: "OP_3DUP", + }, + { + name: "dup too much", + before: [][]byte{}, + script: []byte{btcscript.OP_DUP}, + expectedReturn: btcscript.StackErrUnderflow, + after: [][]byte{}, + disassembly: "OP_DUP", + }, + { + name: "2dup too much", + before: [][]byte{{1}}, + script: []byte{btcscript.OP_2DUP}, + expectedReturn: btcscript.StackErrUnderflow, + after: [][]byte{}, + disassembly: "OP_2DUP", + }, + { + name: "2dup way too much", + before: [][]byte{}, + script: []byte{btcscript.OP_2DUP}, + expectedReturn: btcscript.StackErrUnderflow, + after: [][]byte{}, + disassembly: "OP_2DUP", + }, + { + name: "3dup too much", + before: [][]byte{{1}, {2}}, + script: []byte{btcscript.OP_3DUP}, + expectedReturn: btcscript.StackErrUnderflow, + after: [][]byte{}, + disassembly: "OP_3DUP", + }, + { + name: "3dup kinda too much", + before: [][]byte{{1}}, + script: []byte{btcscript.OP_3DUP}, + expectedReturn: btcscript.StackErrUnderflow, + after: [][]byte{}, + disassembly: "OP_3DUP", + }, + { + name: "3dup way too much", + before: [][]byte{}, + script: []byte{btcscript.OP_3DUP}, + expectedReturn: btcscript.StackErrUnderflow, + after: [][]byte{}, + disassembly: "OP_3DUP", + }, + { + name: "Nip", + before: [][]byte{{1}, {2}, {3}}, + script: []byte{btcscript.OP_NIP}, + after: [][]byte{{1}, {3}}, + disassembly: "OP_NIP", + }, + { + name: "Nip too much", + before: [][]byte{{1}}, + script: []byte{btcscript.OP_NIP}, + expectedReturn: btcscript.StackErrUnderflow, + after: [][]byte{{2}, {3}}, + disassembly: "OP_NIP", + }, + { + name: "keep on tucking", + before: [][]byte{{1}, {2}, {3}}, + script: []byte{btcscript.OP_TUCK}, + after: [][]byte{{1}, {3}, {2}, {3}}, + disassembly: "OP_TUCK", + }, + { + name: "a little tucked up", + before: [][]byte{{1}}, // too few arguments for tuck + script: []byte{btcscript.OP_TUCK}, + expectedReturn: btcscript.StackErrUnderflow, + after: [][]byte{}, + disassembly: "OP_TUCK", + }, + { + name: "all tucked up", + before: [][]byte{}, // too few arguments for tuck + script: []byte{btcscript.OP_TUCK}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_TUCK", + }, + { + name: "drop 1", + before: [][]byte{{1}, {2}, {3}, {4}}, + script: []byte{btcscript.OP_DROP}, + after: [][]byte{{1}, {2}, {3}}, + disassembly: "OP_DROP", + }, + { + name: "drop 2", + before: [][]byte{{1}, {2}, {3}, {4}}, + script: []byte{btcscript.OP_2DROP}, + after: [][]byte{{1}, {2}}, + disassembly: "OP_2DROP", + }, + { + name: "drop too much", + before: [][]byte{}, + script: []byte{btcscript.OP_DROP}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_DROP", + }, + { + name: "2drop too much", + before: [][]byte{{1}}, + script: []byte{btcscript.OP_2DROP}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_2DROP", + }, + { + name: "2drop far too much", + before: [][]byte{}, + script: []byte{btcscript.OP_2DROP}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_2DROP", + }, + { + name: "Rot1", + before: [][]byte{{1}, {2}, {3}, {4}}, + script: []byte{btcscript.OP_ROT}, + after: [][]byte{{1}, {3}, {4}, {2}}, + disassembly: "OP_ROT", + }, + { + name: "Rot2", + before: [][]byte{{1}, {2}, {3}, {4}, {5}, {6}}, + script: []byte{btcscript.OP_2ROT}, + after: [][]byte{{3}, {4}, {5}, {6}, {1}, {2}}, + disassembly: "OP_2ROT", + }, + { + name: "Rot too little", + before: [][]byte{{1}, {2}}, + script: []byte{btcscript.OP_ROT}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_ROT", + }, + { + name: "Swap1", + before: [][]byte{{1}, {2}, {3}, {4}}, + script: []byte{btcscript.OP_SWAP}, + after: [][]byte{{1}, {2}, {4}, {3}}, + disassembly: "OP_SWAP", + }, + { + name: "Swap2", + before: [][]byte{{1}, {2}, {3}, {4}}, + script: []byte{btcscript.OP_2SWAP}, + after: [][]byte{{3}, {4}, {1}, {2}}, + disassembly: "OP_2SWAP", + }, + { + name: "Swap too little", + before: [][]byte{{1}}, + script: []byte{btcscript.OP_SWAP}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_SWAP", + }, + { + name: "Over1", + before: [][]byte{{1}, {2}, {3}, {4}}, + script: []byte{btcscript.OP_OVER}, + after: [][]byte{{1}, {2}, {3}, {4}, {3}}, + disassembly: "OP_OVER", + }, + { + name: "Over2", + before: [][]byte{{1}, {2}, {3}, {4}}, + script: []byte{btcscript.OP_2OVER}, + after: [][]byte{{1}, {2}, {3}, {4}, {1}, {2}}, + disassembly: "OP_2OVER", + }, + { + name: "Over too little", + before: [][]byte{{1}}, + script: []byte{btcscript.OP_OVER}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_OVER", + }, + { + name: "Pick1", + before: [][]byte{{1}, {2}, {3}, {4}, {1}}, + script: []byte{btcscript.OP_PICK}, + after: [][]byte{{1}, {2}, {3}, {4}, {3}}, + disassembly: "OP_PICK", + }, + { + name: "Pick2", + before: [][]byte{{1}, {2}, {3}, {4}, {2}}, + script: []byte{btcscript.OP_PICK}, + after: [][]byte{{1}, {2}, {3}, {4}, {2}}, + disassembly: "OP_PICK", + }, + { + name: "Pick too little", + before: [][]byte{{1}, {1}}, + script: []byte{btcscript.OP_PICK}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_PICK", + }, + { + name: "Pick nothing", + before: [][]byte{{}}, + script: []byte{btcscript.OP_PICK}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_PICK", + }, + { + name: "Pick no args", + before: [][]byte{}, + script: []byte{btcscript.OP_PICK}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_PICK", + }, + { + name: "Pick stupid numbers", + before: [][]byte{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, + script: []byte{btcscript.OP_PICK}, + expectedReturn: btcscript.StackErrNumberTooBig, + disassembly: "OP_PICK", + }, + { + name: "Roll1", + before: [][]byte{{1}, {2}, {3}, {4}, {1}}, + script: []byte{btcscript.OP_ROLL}, + after: [][]byte{{1}, {2}, {4}, {3}}, + disassembly: "OP_ROLL", + }, + { + name: "Roll2", + before: [][]byte{{1}, {2}, {3}, {4}, {2}}, + script: []byte{btcscript.OP_ROLL}, + after: [][]byte{{1}, {3}, {4}, {2}}, + disassembly: "OP_ROLL", + }, + { + name: "Roll too little", + before: [][]byte{{1}, {1}}, + script: []byte{btcscript.OP_ROLL}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_ROLL", + }, + { + name: "Roll nothing ", + before: [][]byte{{1}}, + script: []byte{btcscript.OP_ROLL}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_ROLL", + }, + { + name: "Roll no args ", + before: [][]byte{}, + script: []byte{btcscript.OP_ROLL}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_ROLL", + }, + { + name: "Roll stupid numbers", + before: [][]byte{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, + script: []byte{btcscript.OP_ROLL}, + expectedReturn: btcscript.StackErrNumberTooBig, + disassembly: "OP_ROLL", + }, + { + name: "ifdup (positive)", + before: [][]byte{{1}}, + script: []byte{btcscript.OP_IFDUP}, + after: [][]byte{{1}, {1}}, + disassembly: "OP_IFDUP", + }, + { + name: "ifdup (negative)", + before: [][]byte{{0}}, + script: []byte{btcscript.OP_IFDUP}, + after: [][]byte{{0}}, + disassembly: "OP_IFDUP", + }, + { + name: "ifdup (empty)", + before: [][]byte{}, + script: []byte{btcscript.OP_IFDUP}, + expectedReturn: btcscript.StackErrUnderflow, + after: [][]byte{{0}}, + disassembly: "OP_IFDUP", + }, + { + name: "toaltastack", + before: [][]byte{{1}}, + altbefore: [][]byte{}, + script: []byte{btcscript.OP_TOALTSTACK}, + after: [][]byte{}, + altafter: [][]byte{{1}}, + disassembly: "OP_TOALTSTACK", + }, + { + name: "toaltastack (empty)", + before: [][]byte{}, + altbefore: [][]byte{}, + script: []byte{btcscript.OP_TOALTSTACK}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_TOALTSTACK", + }, + { + name: "fromaltastack", + before: [][]byte{}, + altbefore: [][]byte{{1}}, + script: []byte{btcscript.OP_FROMALTSTACK}, + after: [][]byte{{1}}, + altafter: [][]byte{}, + disassembly: "OP_FROMALTSTACK", + }, + { + name: "fromaltastack (empty)", + before: [][]byte{}, + altbefore: [][]byte{}, + script: []byte{btcscript.OP_FROMALTSTACK}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_FROMALTSTACK", + }, + { + name: "op_size (1)", + before: [][]byte{{1}}, + script: []byte{btcscript.OP_SIZE}, + after: [][]byte{{1}, {1}}, + disassembly: "OP_SIZE", + }, + { + name: "op_size (5)", + before: [][]byte{{1, 2, 3, 4, 5}}, + script: []byte{btcscript.OP_SIZE}, + after: [][]byte{{1, 2, 3, 4, 5}, {5}}, + disassembly: "OP_SIZE", + }, + { + name: "op_size (0)", + before: [][]byte{{}}, + script: []byte{btcscript.OP_SIZE}, + // pushInt(0) actually gives an empty array, still counts as 0 + after: [][]byte{{}, {}}, + disassembly: "OP_SIZE", + }, + { + name: "op_size (invalid)", + before: [][]byte{}, + script: []byte{btcscript.OP_SIZE}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_SIZE", + }, + { + name: "OP_EQUAL (valid)", + before: [][]byte{{1, 2, 3, 4}, {1, 2, 3, 4}}, + script: []byte{btcscript.OP_EQUAL}, + after: [][]byte{{1}}, + disassembly: "OP_EQUAL", + }, + { + name: "OP_EQUAL (invalid)", + before: [][]byte{{1, 2, 3, 4}, {1, 2, 3, 3}}, + script: []byte{btcscript.OP_EQUAL}, + after: [][]byte{{0}}, + disassembly: "OP_EQUAL", + }, + { + name: "OP_EQUAL (one arg)", + before: [][]byte{{1, 2, 3, 4}}, + script: []byte{btcscript.OP_EQUAL}, + expectedReturn: btcscript.StackErrUnderflow, + after: [][]byte{{0}}, + disassembly: "OP_EQUAL", + }, + { + name: "OP_EQUAL (no arg)", + before: [][]byte{}, + script: []byte{btcscript.OP_EQUAL}, + expectedReturn: btcscript.StackErrUnderflow, + after: [][]byte{{0}}, + disassembly: "OP_EQUAL", + }, + { + name: "OP_EQUALVERIFY (valid)", + before: [][]byte{{1, 2, 3, 4}, {1, 2, 3, 4}}, + script: []byte{btcscript.OP_EQUALVERIFY}, + after: [][]byte{}, + disassembly: "OP_EQUALVERIFY", + }, + { + name: "OP_EQUALVERIFY (invalid)", + before: [][]byte{{1, 2, 3, 4}, {1, 2, 3, 3}}, + script: []byte{btcscript.OP_EQUALVERIFY}, + expectedReturn: btcscript.StackErrVerifyFailed, + after: [][]byte{}, + disassembly: "OP_EQUALVERIFY", + }, + { + name: "OP_EQUALVERIFY (one arg)", + before: [][]byte{{1, 2, 3, 4}}, + script: []byte{btcscript.OP_EQUALVERIFY}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_EQUALVERIFY", + }, + { + name: "OP_EQUALVERIFY (no arg)", + before: [][]byte{}, + script: []byte{btcscript.OP_EQUALVERIFY}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_EQUALVERIFY", + }, + { + name: "OP_1NEGATE", + before: [][]byte{}, + script: []byte{btcscript.OP_1NEGATE}, + after: [][]byte{{0x81}}, + disassembly: "OP_1NEGATE", + }, + { + name: "add one to minus one", + before: [][]byte{}, + script: []byte{btcscript.OP_1NEGATE, btcscript.OP_1ADD}, + after: [][]byte{{}}, // 0 + disassembly: "OP_1NEGATE OP_1ADD", + }, + { + name: "OP_ABS (positive)", + before: [][]byte{{1}}, + script: []byte{btcscript.OP_ABS}, + after: [][]byte{{1}}, + disassembly: "OP_ABS", + }, + { + name: "OP_ABS (negative)", + before: [][]byte{{0x81}}, + script: []byte{btcscript.OP_ABS}, + after: [][]byte{{1}}, + disassembly: "OP_ABS", + }, + { + name: "OP_ABS (empty)", + before: [][]byte{}, + script: []byte{btcscript.OP_ABS}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_ABS", + }, + { + name: "op_data_1", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_1, 1}, + after: [][]byte{{1}}, + disassembly: "01", + }, + { + name: "op_data_2", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_2, 1, 2}, + after: [][]byte{{1, 2}}, + disassembly: "0102", + }, + { + name: "op_data_3", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_3, 1, 2, 3}, + after: [][]byte{{1, 2, 3}}, + disassembly: "010203", + }, + { + name: "op_data_4", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_4, 1, 2, 3, 4}, + after: [][]byte{{1, 2, 3, 4}}, + disassembly: "01020304", + }, + { + name: "op_data_5", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_5, 1, 2, 3, 4, 5}, + after: [][]byte{{1, 2, 3, 4, 5}}, + disassembly: "0102030405", + }, + { + name: "op_data_6", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_6, 1, 2, 3, 4, 5, 6}, + after: [][]byte{{1, 2, 3, 4, 5, 6}}, + disassembly: "010203040506", + }, + { + name: "op_data_7", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_7, 1, 2, 3, 4, 5, 6, 7}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7}}, + disassembly: "01020304050607", + }, + { + name: "op_data_8", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_8, 1, 2, 3, 4, 5, 6, 7, 8}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8}}, + disassembly: "0102030405060708", + }, + { + name: "op_data_9", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_9, 1, 2, 3, 4, 5, 6, 7, 8, 9}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9}}, + disassembly: "010203040506070809", + }, + { + name: "op_data_10", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}, + disassembly: "0102030405060708090a", + }, + { + name: "op_data_11", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_11, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}, + disassembly: "0102030405060708090a0b", + }, + { + name: "op_data_12", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_12, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}}, + disassembly: "0102030405060708090a0b0c", + }, + { + name: "op_data_13", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_13, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}}, + disassembly: "0102030405060708090a0b0c0d", + }, + { + name: "op_data_14", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_14, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}}, + disassembly: "0102030405060708090a0b0c0d0e", + }, + { + name: "op_data_15", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_15, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15}}, + disassembly: "0102030405060708090a0b0c0d0e0f", + }, + { + name: "op_data_16", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_16, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16}}, + disassembly: "0102030405060708090a0b0c0d0e0f10", + }, + { + name: "op_data_17", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_17, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17}}, + disassembly: "0102030405060708090a0b0c0d0e0f1011", + }, + { + name: "op_data_18", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_18, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112", + }, + { + name: "op_data_19", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_19, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19}}, + disassembly: "0102030405060708090a0b0c0d0e0f10111213", + }, + { + name: "op_data_20", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_20, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20}}, + disassembly: "0102030405060708090a0b0c0d0e0f1011121314", + }, + { + name: "op_data_21", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_21, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415", + }, + { + name: "op_data_22", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_22, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22}}, + disassembly: "0102030405060708090a0b0c0d0e0f10111213141516", + }, + { + name: "op_data_23", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_23, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23}}, + disassembly: "0102030405060708090a0b0c0d0e0f1011121314151617", + }, + { + name: "op_data_24", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_24, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718", + }, + { + name: "op_data_25", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_25, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}}, + disassembly: "0102030405060708090a0b0c0d0e0f10111213141516171819", + }, + { + name: "op_data_26", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_26, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a", + }, + { + name: "op_data_27", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_27, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b", + }, + { + name: "op_data_28", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_28, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c", + }, + { + name: "op_data_29", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_29, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d", + }, + { + name: "op_data_30", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_30, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e", + }, + { + name: "op_data_31", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_31, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + }, + { + name: "op_data_32", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_32, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + }, + { + name: "op_data_33", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_33, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021", + }, + { + name: "op_data_34", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_34, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122", + }, + { + name: "op_data_35", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_35, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223", + }, + { + name: "op_data_36", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_36, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324", + }, + { + name: "op_data_37", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_37, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425", + }, + { + name: "op_data_38", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_38, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223242526", + }, + { + name: "op_data_39", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_39, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324252627", + }, + { + name: "op_data_40", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_40, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728", + }, + { + name: "op_data_41", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_41, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223242526272829", + }, + { + name: "op_data_42", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_42, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a", + }, + { + name: "op_data_43", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_43, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b", + }, + { + name: "op_data_44", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_44, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c", + }, + { + name: "op_data_45", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_45, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d", + }, + { + name: "op_data_46", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_46, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e", + }, + { + name: "op_data_47", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_47, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", + }, + { + name: "op_data_48", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_48, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30", + }, + { + name: "op_data_49", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_49, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031", + }, + { + name: "op_data_50", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_50, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132", + }, + { + name: "op_data_51", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_51, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233", + }, + { + name: "op_data_52", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_52, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334", + }, + { + name: "op_data_53", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_53, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435", + }, + { + name: "op_data_54", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_54, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343536", + }, + { + name: "op_data_55", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_55, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637", + }, + { + name: "op_data_56", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_56, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738", + }, + { + name: "op_data_57", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_57, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343536373839", + }, + { + name: "op_data_58", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_58, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a", + }, + { + name: "op_data_59", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_59, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b", + }, + { + name: "op_data_60", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_60, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c", + }, + { + name: "op_data_61", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_61, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d", + }, + { + name: "op_data_62", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_62, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e", + }, + { + name: "op_data_63", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_63, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + }, + { + name: "op_data_64", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_64, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40", + }, + { + name: "op_data_65", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_65, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 65}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f4041", + }, + { + name: "op_data_66", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_66, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 65, 66}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142", + }, + { + name: "op_data_67", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_67, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 65, 66, 67}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243", + }, + { + name: "op_data_68", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_68, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f4041424344", + }, + { + name: "op_data_69", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_69, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445", + }, + { + name: "op_data_70", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_70, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243444546", + }, + { + name: "op_data_71", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_71, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f4041424344454647", + }, + { + name: "op_data_72", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_72, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748", + }, + { + name: "op_data_73", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_73, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243444546474849", + }, + { + name: "op_data_74", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_74, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + }}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a", + }, + { + name: "op_data_75", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_75, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75}, + after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75}}, + disassembly: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b", + }, + { + name: "op_data too short", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_2, 1}, + expectedReturn: btcscript.StackErrShortScript, + disassemblyerr: btcscript.StackErrShortScript, + }, + { + name: "op_pushdata_1", + before: [][]byte{}, + script: []byte{btcscript.OP_PUSHDATA1, 1, 2}, + after: [][]byte{{2}}, + disassembly: "02", + }, + { + name: "op_pushdata_1 too short", + script: []byte{btcscript.OP_PUSHDATA1, 1}, + expectedReturn: btcscript.StackErrShortScript, + disassemblyerr: btcscript.StackErrShortScript, + }, + { + name: "op_pushdata_2", + before: [][]byte{}, + script: []byte{btcscript.OP_PUSHDATA2, 2, 0, 2, 4}, + after: [][]byte{{2, 4}}, + disassembly: "0204", + }, + { + name: "op_pushdata_2 too short", + script: []byte{btcscript.OP_PUSHDATA2, 2, 0}, + expectedReturn: btcscript.StackErrShortScript, + disassemblyerr: btcscript.StackErrShortScript, + }, + { + name: "op_pushdata_4", + before: [][]byte{}, + script: []byte{btcscript.OP_PUSHDATA4, 4, 0, 0, 0, 2, 4, 8, 16}, + after: [][]byte{{2, 4, 8, 16}}, + disassembly: "02040810", + }, + { + name: "op_pushdata_4 too short", + script: []byte{btcscript.OP_PUSHDATA4, 4, 0, 0, 0}, + expectedReturn: btcscript.StackErrShortScript, + disassemblyerr: btcscript.StackErrShortScript, + }, + // XXX also pushdata cases where the pushed data isn't long enough, + // no real error type defined for that as of yet. + + { + name: "OP_SHA1 no args", + before: [][]byte{}, + script: []byte{btcscript.OP_SHA1}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_SHA1", + }, + { + name: "OP_SHA256 no args", + before: [][]byte{}, + script: []byte{btcscript.OP_SHA256}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_SHA256", + }, + { + name: "OP_RIPEMD160 no args", + before: [][]byte{}, + script: []byte{btcscript.OP_RIPEMD160}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_RIPEMD160", + }, + // data taken from transaction + // 4cbb6924e5f9788d7fcf0a1ce8c175bf9befa43eb5e23386b69bc4dce49da71c + // in block 103307 + // First do it in component parts to make sure the sha256 and ripemd160 + // opcodes work + { + name: "op_hash160 the hard way", + before: [][]byte{{0x04, 0x0f, 0xa4, 0x92, 0xe3, 0x59, 0xde, 0xe8, 0x4b, + 0x53, 0xfe, 0xc5, 0xe9, 0x18, 0xb7, 0xfd, 0x62, 0x1e, + 0xb7, 0xe5, 0x63, 0x38, 0xc5, 0xfb, 0xff, 0x71, 0xd9, + 0x1d, 0x17, 0x22, 0xda, 0x58, 0xf1, 0x0f, 0x9e, 0x8f, + 0x41, 0x2f, 0x39, 0x9c, 0xb3, 0x06, 0x70, 0xa7, 0x27, + 0xe9, 0x91, 0x94, 0xaa, 0x69, 0x27, 0xaf, 0xf2, 0x54, + 0x16, 0xec, 0x48, 0x9d, 0x45, 0x3a, 0x80, 0x7e, 0x03, + 0xc0, 0x83}}, + script: []byte{btcscript.OP_SHA256, btcscript.OP_RIPEMD160}, + after: [][]byte{{0x8b, 0xfa, 0x5c, 0x1f, 0x68, 0x5f, 0x13, 0x86, 0x3e, + 0x74, 0x2e, 0x1b, 0xaf, 0x15, 0xf1, 0x71, 0xad, 0x49, + 0x8b, 0x8f}}, + disassembly: "OP_SHA256 OP_RIPEMD160", + }, + // Then test it the ``normal'' way. + { + name: "op_hash160", + before: [][]byte{{0x04, 0x0f, 0xa4, 0x92, 0xe3, 0x59, 0xde, 0xe8, 0x4b, + 0x53, 0xfe, 0xc5, 0xe9, 0x18, 0xb7, 0xfd, 0x62, 0x1e, + 0xb7, 0xe5, 0x63, 0x38, 0xc5, 0xfb, 0xff, 0x71, 0xd9, + 0x1d, 0x17, 0x22, 0xda, 0x58, 0xf1, 0x0f, 0x9e, 0x8f, + 0x41, 0x2f, 0x39, 0x9c, 0xb3, 0x06, 0x70, 0xa7, 0x27, + 0xe9, 0x91, 0x94, 0xaa, 0x69, 0x27, 0xaf, 0xf2, 0x54, + 0x16, 0xec, 0x48, 0x9d, 0x45, 0x3a, 0x80, 0x7e, 0x03, + 0xc0, 0x83}}, + script: []byte{btcscript.OP_HASH160}, + after: [][]byte{{0x8b, 0xfa, 0x5c, 0x1f, 0x68, 0x5f, 0x13, 0x86, 0x3e, + 0x74, 0x2e, 0x1b, 0xaf, 0x15, 0xf1, 0x71, 0xad, 0x49, + 0x8b, 0x8f}}, + disassembly: "OP_HASH160", + }, + // now with pushing. (mostly to check the disassembly) + { + name: "op_hash160 full script", + before: [][]byte{}, + script: []byte{btcscript.OP_DATA_65, + 0x04, 0x0f, 0xa4, 0x92, 0xe3, 0x59, 0xde, 0xe8, 0x4b, + 0x53, 0xfe, 0xc5, 0xe9, 0x18, 0xb7, 0xfd, 0x62, 0x1e, + 0xb7, 0xe5, 0x63, 0x38, 0xc5, 0xfb, 0xff, 0x71, 0xd9, + 0x1d, 0x17, 0x22, 0xda, 0x58, 0xf1, 0x0f, 0x9e, 0x8f, + 0x41, 0x2f, 0x39, 0x9c, 0xb3, 0x06, 0x70, 0xa7, 0x27, + 0xe9, 0x91, 0x94, 0xaa, 0x69, 0x27, 0xaf, 0xf2, 0x54, + 0x16, 0xec, 0x48, 0x9d, 0x45, 0x3a, 0x80, 0x7e, 0x03, + 0xc0, 0x83, + btcscript.OP_HASH160, btcscript.OP_DATA_20, + 0x8b, 0xfa, 0x5c, 0x1f, 0x68, 0x5f, 0x13, 0x86, 0x3e, + 0x74, 0x2e, 0x1b, 0xaf, 0x15, 0xf1, 0x71, 0xad, 0x49, + 0x8b, 0x8f, + btcscript.OP_EQUALVERIFY}, + after: [][]byte{}, + disassembly: "040fa492e359dee84b53fec5e918b7fd621eb7e56338c5fbff71d91d1722da58f10f9e8f412f399cb30670a727e99194aa6927aff25416ec489d453a807e03c083 OP_HASH160 8bfa5c1f685f13863e742e1baf15f171ad498b8f OP_EQUALVERIFY", + }, + { + name: "op_hash160 no args", + script: []byte{btcscript.OP_HASH160}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_HASH160", + }, + // hash256 test taken from spend of: + // 09f691b2263260e71f363d1db51ff3100d285956a40cc0e4f8c8c2c4a80559b1 + { + name: "op_hash256", + before: [][]byte{{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3b, 0xa3, 0xed, 0xfd, 0x7a, 0x7b, 0x12, 0xb2, + 0x7a, 0xc7, 0x2c, 0x3e, 0x67, 0x76, 0x8f, 0x61, 0x7f, + 0xc8, 0x1b, 0xc3, 0x88, 0x8a, 0x51, 0x32, 0x3a, 0x9f, + 0xb8, 0xaa, 0x4b, 0x1e, 0x5e, 0x4a, 0x29, 0xab, 0x5f, + 0x49, 0xff, 0xff, 0x00, 0x1d, 0x1d, 0xac, 0x2b, 0x7c}}, + script: []byte{btcscript.OP_HASH256}, + after: [][]byte{{0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72, 0xc1, + 0xa6, 0xa2, 0x46, 0xae, 0x63, 0xf7, 0x4f, 0x93, 0x1e, + 0x83, 0x65, 0xe1, 0x5a, 0x08, 0x9c, 0x68, 0xd6, 0x19, + 0x00, 0x00, 0x00, 0x00, 0x00}}, + disassembly: "OP_HASH256", + }, + { + name: "OP_HASH256 no args", + script: []byte{btcscript.OP_HASH256}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_HASH256", + }, + // We need a more involved setup to test OP_CHECKSIG and + // OP_CHECKMULTISIG (see script_test.go) but we can test it with + // invalid arguments here quite easily. + { + name: "OP_CHECKSIG one arg", + script: []byte{btcscript.OP_1, btcscript.OP_CHECKSIG}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_1 OP_CHECKSIG", + }, + { + name: "OP_CHECKSIG no arg", + script: []byte{btcscript.OP_CHECKSIG}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_CHECKSIG", + }, + { + name: "OP_CHECKSIGVERIFY one arg", + script: []byte{btcscript.OP_1, + btcscript.OP_CHECKSIGVERIFY}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_1 OP_CHECKSIGVERIFY", + }, + { + name: "OP_CHECKSIGVERIFY no arg", + script: []byte{btcscript.OP_CHECKSIGVERIFY}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_CHECKSIGVERIFY", + }, + { + name: "OP_CHECK_MULTISIG no args", + script: []byte{btcscript.OP_CHECK_MULTISIG}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_CHECK_MULTISIG", + }, + { + name: "OP_CHECK_MULTISIG huge number", + script: []byte{btcscript.OP_PUSHDATA1, + 0x9, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, + btcscript.OP_CHECK_MULTISIG}, + expectedReturn: btcscript.StackErrNumberTooBig, + disassembly: "010203040506070809 OP_CHECK_MULTISIG", + }, + { + name: "OP_CHECK_MULTISIG too many keys", + script: []byte{btcscript.OP_DATA_1, 21, + btcscript.OP_CHECK_MULTISIG}, + expectedReturn: btcscript.StackErrTooManyPubkeys, + disassembly: "15 OP_CHECK_MULTISIG", + }, + { + name: "OP_CHECK_MULTISIG lying about pubkeys", + script: []byte{btcscript.OP_1, + btcscript.OP_CHECK_MULTISIG}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_1 OP_CHECK_MULTISIG", + }, + { + // pubkey comes from blockchain + name: "OP_CHECK_MULTISIG no sigs", + script: []byte{ + btcscript.OP_DATA_65, + 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, + 0x13, 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, + 0x15, 0x9b, 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, + 0x71, 0x30, 0x2f, 0xa2, 0x84, 0x14, 0xe7, 0xaa, 0xb3, + 0x73, 0x97, 0xf5, 0x54, 0xa7, 0xdf, 0x5f, 0x14, 0x2c, + 0x21, 0xc1, 0xb7, 0x30, 0x3b, 0x8a, 0x06, 0x26, 0xf1, + 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, + 0xd8, 0x4c, + btcscript.OP_1, + btcscript.OP_CHECK_MULTISIG}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECK_MULTISIG", + }, + { + // pubkey comes from blockchain + name: "OP_CHECK_MULTISIG sigs huge no", + script: []byte{ + btcscript.OP_PUSHDATA1, + 0x9, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, + btcscript.OP_DATA_65, + 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, + 0x13, 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, + 0x15, 0x9b, 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, + 0x71, 0x30, 0x2f, 0xa2, 0x84, 0x14, 0xe7, 0xaa, 0xb3, + 0x73, 0x97, 0xf5, 0x54, 0xa7, 0xdf, 0x5f, 0x14, 0x2c, + 0x21, 0xc1, 0xb7, 0x30, 0x3b, 0x8a, 0x06, 0x26, 0xf1, + 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, + 0xd8, 0x4c, + btcscript.OP_1, + btcscript.OP_CHECK_MULTISIG}, + expectedReturn: btcscript.StackErrNumberTooBig, + disassembly: "010203040506070809 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECK_MULTISIG", + }, + { + name: "OP_CHECK_MULTISIG too few sigs", + script: []byte{btcscript.OP_1, + btcscript.OP_DATA_65, + 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, + 0x13, 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, + 0x15, 0x9b, 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, + 0x71, 0x30, 0x2f, 0xa2, 0x84, 0x14, 0xe7, 0xaa, 0xb3, + 0x73, 0x97, 0xf5, 0x54, 0xa7, 0xdf, 0x5f, 0x14, 0x2c, + 0x21, 0xc1, 0xb7, 0x30, 0x3b, 0x8a, 0x06, 0x26, 0xf1, + 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, + 0xd8, 0x4c, + btcscript.OP_1, + btcscript.OP_CHECK_MULTISIG}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECK_MULTISIG", + }, + { + // pubkey and sig comes from blockchain, are unrelated + name: "OP_CHECK_MULTISIG won't verify", + script: []byte{btcscript.OP_1, + btcscript.OP_DATA_71, + 0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69, 0x32, + 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1, 0xa2, + 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6, 0x24, + 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd, 0x41, + 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca, 0x07, + 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90, 0x9d, + 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22, 0x08, + 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09, 0x01, + btcscript.OP_1, + btcscript.OP_DATA_65, + 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, + 0x13, 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, + 0x15, 0x9b, 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, + 0x71, 0x30, 0x2f, 0xa2, 0x84, 0x14, 0xe7, 0xaa, 0xb3, + 0x73, 0x97, 0xf5, 0x54, 0xa7, 0xdf, 0x5f, 0x14, 0x2c, + 0x21, 0xc1, 0xb7, 0x30, 0x3b, 0x8a, 0x06, 0x26, 0xf1, + 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, + 0xd8, 0x4c, + btcscript.OP_1, + btcscript.OP_CHECK_MULTISIG}, + after: [][]byte{{0}}, + disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECK_MULTISIG", + }, + { + // invalid pubkey means that it fails to validate, not an + // error. There are pubkeys in the blockchain that don't + // parse with any validity. + name: "OP_CHECK_MULTISIG sigs bad pubkey", + script: []byte{btcscript.OP_1, + btcscript.OP_DATA_71, + 0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69, 0x32, + 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1, 0xa2, + 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6, 0x24, + 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd, 0x41, + 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca, 0x07, + 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90, 0x9d, + 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22, 0x08, + 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09, 0x01, + btcscript.OP_1, + btcscript.OP_1, btcscript.OP_1, + btcscript.OP_CHECK_MULTISIG}, + after: [][]byte{{0}}, + disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 OP_1 OP_1 OP_CHECK_MULTISIG", + }, + // XXX(oga) Test multisig when extra arg is missing. needs valid sig. + // disabled opcodes + { + name: "OP_CHECKMULTISIGVERIFY no args", + script: []byte{btcscript.OP_CHECKMULTISIGVERIFY}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_CHECKMULTISIGVERIFY", + }, + { + name: "OP_CHECKMULTISIGVERIFY huge number", + script: []byte{btcscript.OP_PUSHDATA1, + 0x9, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, + btcscript.OP_CHECKMULTISIGVERIFY}, + expectedReturn: btcscript.StackErrNumberTooBig, + disassembly: "010203040506070809 OP_CHECKMULTISIGVERIFY", + }, + { + name: "OP_CHECKMULTISIGVERIFY too many keys", + script: []byte{btcscript.OP_DATA_1, 21, + btcscript.OP_CHECKMULTISIGVERIFY}, + expectedReturn: btcscript.StackErrTooManyPubkeys, + disassembly: "15 OP_CHECKMULTISIGVERIFY", + }, + { + name: "OP_CHECKMULTISIGVERIFY lying about pubkeys", + script: []byte{btcscript.OP_1, + btcscript.OP_CHECKMULTISIGVERIFY}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_1 OP_CHECKMULTISIGVERIFY", + }, + { + // pubkey comes from blockchain + name: "OP_CHECKMULTISIGVERIFY no sigs", + script: []byte{ + btcscript.OP_DATA_65, + 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, + 0x13, 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, + 0x15, 0x9b, 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, + 0x71, 0x30, 0x2f, 0xa2, 0x84, 0x14, 0xe7, 0xaa, 0xb3, + 0x73, 0x97, 0xf5, 0x54, 0xa7, 0xdf, 0x5f, 0x14, 0x2c, + 0x21, 0xc1, 0xb7, 0x30, 0x3b, 0x8a, 0x06, 0x26, 0xf1, + 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, + 0xd8, 0x4c, + btcscript.OP_1, + btcscript.OP_CHECKMULTISIGVERIFY}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIGVERIFY", + }, + { + name: "OP_CHECKMULTISIGVERIFY sigs huge no", + script: []byte{ + btcscript.OP_PUSHDATA1, + 0x9, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, + btcscript.OP_DATA_65, + 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, + 0x13, 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, + 0x15, 0x9b, 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, + 0x71, 0x30, 0x2f, 0xa2, 0x84, 0x14, 0xe7, 0xaa, 0xb3, + 0x73, 0x97, 0xf5, 0x54, 0xa7, 0xdf, 0x5f, 0x14, 0x2c, + 0x21, 0xc1, 0xb7, 0x30, 0x3b, 0x8a, 0x06, 0x26, 0xf1, + 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, + 0xd8, 0x4c, + btcscript.OP_1, + btcscript.OP_CHECKMULTISIGVERIFY}, + expectedReturn: btcscript.StackErrNumberTooBig, + disassembly: "010203040506070809 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIGVERIFY", + }, + { + name: "OP_CHECKMULTISIGVERIFY too few sigs", + script: []byte{btcscript.OP_1, + btcscript.OP_DATA_65, + 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, + 0x13, 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, + 0x15, 0x9b, 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, + 0x71, 0x30, 0x2f, 0xa2, 0x84, 0x14, 0xe7, 0xaa, 0xb3, + 0x73, 0x97, 0xf5, 0x54, 0xa7, 0xdf, 0x5f, 0x14, 0x2c, + 0x21, 0xc1, 0xb7, 0x30, 0x3b, 0x8a, 0x06, 0x26, 0xf1, + 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, + 0xd8, 0x4c, + btcscript.OP_1, + btcscript.OP_CHECKMULTISIGVERIFY}, + expectedReturn: btcscript.StackErrUnderflow, + disassembly: "OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIGVERIFY", + }, + { + // pubkey and sig comes from blockchain, are unrelated + name: "OP_CHECKMULTISIGVERIFY won't verify", + script: []byte{btcscript.OP_1, + btcscript.OP_DATA_71, + 0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69, 0x32, + 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1, 0xa2, + 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6, 0x24, + 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd, 0x41, + 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca, 0x07, + 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90, 0x9d, + 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22, 0x08, + 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09, 0x01, + btcscript.OP_1, + btcscript.OP_DATA_65, + 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, + 0x13, 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, + 0x15, 0x9b, 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, + 0x71, 0x30, 0x2f, 0xa2, 0x84, 0x14, 0xe7, 0xaa, 0xb3, + 0x73, 0x97, 0xf5, 0x54, 0xa7, 0xdf, 0x5f, 0x14, 0x2c, + 0x21, 0xc1, 0xb7, 0x30, 0x3b, 0x8a, 0x06, 0x26, 0xf1, + 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, + 0xd8, 0x4c, + btcscript.OP_1, + btcscript.OP_CHECKMULTISIGVERIFY}, + expectedReturn: btcscript.StackErrVerifyFailed, + disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIGVERIFY", + }, + { + // invalid pubkey means that it fails to validate, not an + // error. There are pubkeys in the blockchain that don't + // parse with any validity. + name: "OP_CHECKMULTISIGVERIFY sigs bad pubkey", + script: []byte{btcscript.OP_1, + btcscript.OP_DATA_71, + 0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69, 0x32, + 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1, 0xa2, + 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6, 0x24, + 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd, 0x41, + 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca, 0x07, + 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90, 0x9d, + 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22, 0x08, + 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09, 0x01, + btcscript.OP_1, + btcscript.OP_1, btcscript.OP_1, + btcscript.OP_CHECKMULTISIGVERIFY}, + expectedReturn: btcscript.StackErrVerifyFailed, + disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 OP_1 OP_1 OP_CHECKMULTISIGVERIFY", + }, + { + name: "OP_CAT disabled", + script: []byte{btcscript.OP_CAT}, + expectedReturn: btcscript.StackErrOpDisabled, + disassembly: "OP_CAT", + }, + { + name: "OP_SUBSTR disabled", + script: []byte{btcscript.OP_SUBSTR}, + expectedReturn: btcscript.StackErrOpDisabled, + disassembly: "OP_SUBSTR", + }, + { + name: "OP_LEFT disabled", + script: []byte{btcscript.OP_LEFT}, + expectedReturn: btcscript.StackErrOpDisabled, + disassembly: "OP_LEFT", + }, + { + name: "OP_RIGHT disabled", + script: []byte{btcscript.OP_RIGHT}, + expectedReturn: btcscript.StackErrOpDisabled, + disassembly: "OP_RIGHT", + }, + { + name: "OP_INVERT disabled", + script: []byte{btcscript.OP_INVERT}, + expectedReturn: btcscript.StackErrOpDisabled, + disassembly: "OP_INVERT", + }, + { + name: "OP_AND disabled", + script: []byte{btcscript.OP_AND}, + expectedReturn: btcscript.StackErrOpDisabled, + disassembly: "OP_AND", + }, + { + name: "OP_OR disabled", + script: []byte{btcscript.OP_OR}, + expectedReturn: btcscript.StackErrOpDisabled, + disassembly: "OP_OR", + }, + { + name: "OP_XOR disabled", + script: []byte{btcscript.OP_XOR}, + expectedReturn: btcscript.StackErrOpDisabled, + disassembly: "OP_XOR", + }, + { + name: "OP_2MUL disabled", + script: []byte{btcscript.OP_2MUL}, + expectedReturn: btcscript.StackErrOpDisabled, + disassembly: "OP_2MUL", + }, + { + name: "OP_2DIV disabled", + script: []byte{btcscript.OP_2DIV}, + expectedReturn: btcscript.StackErrOpDisabled, + disassembly: "OP_2DIV", + }, + { + name: "OP_2DIV disabled", + script: []byte{btcscript.OP_2DIV}, + expectedReturn: btcscript.StackErrOpDisabled, + disassembly: "OP_2DIV", + }, + { + name: "OP_MUL disabled", + script: []byte{btcscript.OP_MUL}, + expectedReturn: btcscript.StackErrOpDisabled, + disassembly: "OP_MUL", + }, + { + name: "OP_DIV disabled", + script: []byte{btcscript.OP_DIV}, + expectedReturn: btcscript.StackErrOpDisabled, + disassembly: "OP_DIV", + }, + { + name: "OP_MOD disabled", + script: []byte{btcscript.OP_MOD}, + expectedReturn: btcscript.StackErrOpDisabled, + disassembly: "OP_MOD", + }, + { + name: "OP_LSHIFT disabled", + script: []byte{btcscript.OP_LSHIFT}, + expectedReturn: btcscript.StackErrOpDisabled, + disassembly: "OP_LSHIFT", + }, + { + name: "OP_RSHIFT disabled", + script: []byte{btcscript.OP_RSHIFT}, + expectedReturn: btcscript.StackErrOpDisabled, + disassembly: "OP_RSHIFT", + }, + // Reserved opcodes + { + name: "OP_RESERVED reserved", + script: []byte{btcscript.OP_RESERVED}, + expectedReturn: btcscript.StackErrReservedOpcode, + disassembly: "OP_RESERVED", + }, + { + name: "OP_VER reserved", + script: []byte{btcscript.OP_VER}, + expectedReturn: btcscript.StackErrReservedOpcode, + disassembly: "OP_VER", + }, + { + name: "OP_VERIF reserved", + script: []byte{btcscript.OP_VERIF}, + expectedReturn: btcscript.StackErrReservedOpcode, + disassembly: "OP_VERIF", + }, + { + name: "OP_VERNOTIF reserved", + script: []byte{btcscript.OP_VERNOTIF}, + expectedReturn: btcscript.StackErrReservedOpcode, + disassembly: "OP_VERNOTIF", + }, + { + name: "OP_RESERVED1 reserved", + script: []byte{btcscript.OP_RESERVED1}, + expectedReturn: btcscript.StackErrReservedOpcode, + disassembly: "OP_RESERVED1", + }, + { + name: "OP_RESERVED2 reserved", + script: []byte{btcscript.OP_RESERVED2}, + expectedReturn: btcscript.StackErrReservedOpcode, + disassembly: "OP_RESERVED2", + }, + // Invalid Opcodes + { + name: "invalid opcode 186", + script: []byte{186}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 187", + script: []byte{187}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 188", + script: []byte{188}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 189", + script: []byte{189}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 190", + script: []byte{190}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 191", + script: []byte{191}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 192", + script: []byte{192}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 193", + script: []byte{193}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 194", + script: []byte{194}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 195", + script: []byte{195}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 196", + script: []byte{196}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 197", + script: []byte{197}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 198", + script: []byte{198}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 199", + script: []byte{199}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 200", + script: []byte{200}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 201", + script: []byte{201}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 202", + script: []byte{202}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 203", + script: []byte{203}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 204", + script: []byte{204}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 205", + script: []byte{205}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 206", + script: []byte{206}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 207", + script: []byte{207}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 208", + script: []byte{208}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 209", + script: []byte{209}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 210", + script: []byte{210}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 211", + script: []byte{211}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 212", + script: []byte{212}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 213", + script: []byte{213}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 214", + script: []byte{214}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 215", + script: []byte{215}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 216", + script: []byte{216}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 217", + script: []byte{217}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 218", + script: []byte{218}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 219", + script: []byte{219}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 220", + script: []byte{220}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 221", + script: []byte{221}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 222", + script: []byte{222}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 223", + script: []byte{223}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 224", + script: []byte{224}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 225", + script: []byte{225}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 226", + script: []byte{226}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 227", + script: []byte{227}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 228", + script: []byte{228}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 229", + script: []byte{229}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 230", + script: []byte{230}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 231", + script: []byte{231}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 232", + script: []byte{232}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 233", + script: []byte{233}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 234", + script: []byte{234}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 235", + script: []byte{235}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 236", + script: []byte{236}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 237", + script: []byte{237}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 238", + script: []byte{238}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 239", + script: []byte{239}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 240", + script: []byte{240}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 241", + script: []byte{241}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 242", + script: []byte{242}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 243", + script: []byte{243}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 244", + script: []byte{244}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 245", + script: []byte{245}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 246", + script: []byte{246}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 247", + script: []byte{247}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 248", + script: []byte{248}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 249", + script: []byte{249}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 250", + script: []byte{250}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 251", + script: []byte{251}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode 252", + script: []byte{252}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassemblyerr: btcscript.StackErrInvalidOpcode, + }, + { + name: "invalid opcode OP_PUBKEY", + script: []byte{btcscript.OP_PUBKEY}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassembly: "OP_PUBKEY", + }, + { + name: "invalid opcode OP_PUBKEYHASH", + script: []byte{btcscript.OP_PUBKEYHASH}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassembly: "OP_PUBKEYHASH", + }, + { + name: "invalid opcode OP_INVALIDOPCODE", + script: []byte{btcscript.OP_INVALIDOPCODE}, + expectedReturn: btcscript.StackErrInvalidOpcode, + disassembly: "OP_INVALIDOPCODE", + }, +} + +func stacksEqual(a, b [][]byte) bool { + if len(a) != len(b) { + return false + } + + for i := range a { + if !bytes.Equal(a[i], b[i]) { + return false + } + } + return true +} + +func testOpcode(t *testing.T, test *detailedTest) { + // mock up fake tx. + tx := &btcwire.MsgTx{ + Version: 1, + TxIn: []*btcwire.TxIn{ + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash{}, + Index: 0xffffffff, + }, + SignatureScript: []byte{}, + Sequence: 0xffffffff, + }, + }, + TxOut: []*btcwire.TxOut{ + &btcwire.TxOut{ + Value: 0x12a05f200, + PkScript: []byte{}, + }, + }, + LockTime: 0, + } + + tx.TxOut[0].PkScript = test.script + + engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript, + tx.TxOut[0].PkScript, 0, tx, 1, false) + if err != nil { + if err != test.expectedReturn { + t.Errorf("Error return not expected %s: %v %v", + test.name, test.expectedReturn, err) + return + } + return + } + engine.SetStack(test.before) + engine.SetAltStack(test.altbefore) + + // test disassembly engine. + // pc is at start of script 1, so check that DisasmScript matches + // DisasmPc. Only run this if we have a disassembly for the test. + // sine one of them have invalid instruction sequences and won't + // disassemble. + var disScript, disPC string + if test.disassembly != "" { + var err error + disScript, err = engine.DisasmScript(1) + if err != nil { + t.Errorf("failed to disassemble script for %s: %v", + test.name, err) + } + } + + done := false + for !done { + if test.disassembly != "" { + disCurPC, err := engine.DisasmPC() + if err != nil { + t.Errorf("failed to disassemble pc for %s: %v", + test.name, err) + } + disPC += disCurPC + "\n" + } + + done, err = engine.Step() + if err != nil { + if err != test.expectedReturn { + t.Errorf("Error return not expected %s: %v %v", + test.name, test.expectedReturn, err) + return + } + return + } + } + if err != test.expectedReturn { + t.Errorf("Error return not expected %s: %v %v", + test.name, test.expectedReturn, err) + } + + if test.disassembly != "" { + if disScript != disPC { + t.Errorf("script disassembly doesn't match pc "+ + "disassembly for %s: pc: \"%s\" script: \"%s\"", + test.name, disScript, disPC) + } + } + + after := engine.GetStack() + if !stacksEqual(after, test.after) { + t.Errorf("Stacks not equal after %s:\ngot: %v\n exp: %v", + test.name, spew.Sdump(after), spew.Sdump(test.after)) + } + altafter := engine.GetAltStack() + if !stacksEqual(altafter, test.altafter) { + t.Errorf("AltStacks not equal after %s:\n got: %v\nexp: %v", + test.name, spew.Sdump(altafter), + spew.Sdump(test.altafter)) + } +} + +func TestOpcodes(t *testing.T) { + for i := range detailedTests { + testOpcode(t, &detailedTests[i]) + } +} + +func testDisasmString(t *testing.T, test *detailedTest) { + // mock up fake tx. + dis, err := btcscript.DisasmString(test.script) + if err != nil { + if err != test.disassemblyerr { + t.Errorf("%s: disassembly got error %v expected %v", test.name, + err, test.disassemblyerr) + } + return + } + if test.disassemblyerr != nil { + t.Errorf("%s: expected error %v, got %s", test.name, + test.disassemblyerr, dis) + return + } + if dis != test.disassembly { + t.Errorf("Disassembly for %s doesn't match expected "+ + "got: \"%s\" expected: \"%s\"", test.name, dis, + test.disassembly) + } +} + +func TestDisasmStrings(t *testing.T) { + for i := range detailedTests { + testDisasmString(t, &detailedTests[i]) + } +} diff --git a/script.go b/script.go new file mode 100644 index 00000000..63629afe --- /dev/null +++ b/script.go @@ -0,0 +1,697 @@ +// Copyright (c) 2013 Conformal Systems LLC. +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcscript + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "github.com/conformal/btcwire" + "github.com/davecgh/go-spew/spew" + "time" +) + +// StackErrShortScript is returned if the script has an opcode that is too long +// for the length of the script. +var StackErrShortScript = errors.New("execute past end of script") + +// StackErrUnderflow is returned if an opcode requires more items on the stack +// than is present. +var StackErrUnderflow = errors.New("stack underflow") + +// StackErrInvalidArgs is returned if the argument for an opcode is out of +// acceptable range. +var StackErrInvalidArgs = errors.New("invalid argument") + +// StackErrOpDisabled is returned when a disabled opcode is encountered in the +// script. +var StackErrOpDisabled = errors.New("Disabled Opcode") + +// StackErrVerifyFailed is returned when one of the OP_VERIFY or OP_*VERIFY +// instructions is executed and the conditions fails. +var StackErrVerifyFailed = errors.New("Verify failed") + +// StackErrNumberTooBig is returned when the argument for an opcode that should +// be an offset is obviously far too large. +var StackErrNumberTooBig = errors.New("number too big") + +// StackErrInvalidOpcode is returned when an opcode marked as invalid or a +// completely undefined opcode is encountered. +var StackErrInvalidOpcode = errors.New("Invalid Opcode") + +// StackErrReservedOpcode is returned when an opcode marked as reserved is +// encountered. +var StackErrReservedOpcode = errors.New("Reserved Opcode") + +// StackErrEarlyReturn is returned when OP_RETURN is exectured in the script. +var StackErrEarlyReturn = errors.New("Script returned early") + +// StackErrNoIf is returned if an OP_ELSE or OP_ENDIF is encountered without +// first having an OP_IF or OP_NOTIF in the script. +var StackErrNoIf = errors.New("OP_ELSE or OP_ENDIF with no matching OP_IF") + +// StackErrMissingEndif is returned if the end of a script is reached without +// and OP_ENDIF to correspond to a conditional expression. +var StackErrMissingEndif = fmt.Errorf("execute fail, in conditional execution") + +// StackErrTooManyPubkeys is returned if an OP_CHECKMULTISIG is encountered +// with more than MaxPubKeysPerMultiSig pubkeys present. +var StackErrTooManyPubkeys = errors.New("Invalid pubkey count in OP_CHECKMULTISIG") + +// StackErrTooManyOperations is returned if a script has more then +// MaxOpsPerScript opcodes that do not push data. +var StackErrTooManyOperations = errors.New("Too many operations in script") + +// StackErrElementTooBig is returned if the size of an element to be pushed to +// the stack is over MaxScriptElementSize. +var StackErrElementTooBig = errors.New("Element in script too large") + +// StackErrUnknownAddress is returned when ScriptToAddress does not recognise +// the pattern of the script and thus can not find the address for payment. +var StackErrUnknownAddress = fmt.Errorf("non-recognised address") + +// StackErrScriptFailed is returned when at the end of a script the boolean +// on top of the stack is false signifying that the script has failed. +var StackErrScriptFailed = fmt.Errorf("execute fail, fail on stack") + +// Bip16Activation is the timestamp where BIP0016 is valid to use in the +// blockchain. To be used to determine if BIP0016 should be called for or not. +// This timestamp corresponds to Sun Apr 1 00:00:00 UTC 2012. +var Bip16Activation = time.Unix(1333238400, 0) + +// Hash type bits from the end of a signature. +const ( + SigHashOld = 0x0 + SigHashAll = 0x1 + SigHashNone = 0x2 + SigHashSingle = 0x3 + SigHashAnyOneCanPay = 0x80 +) + +// These are the constants specified for maximums in individual scripts. +const ( + MaxOpsPerScript = 201 // Max number of non-push operations. + MaxPubKeysPerMultiSig = 20 // Multisig can't have more sigs than this. + MaxScriptElementSize = 520 // Max bytes pushable to the stack. +) + +// ScriptType is an enumeration for the list of standard types of script. +type scriptType byte + +// Types of script payment known about in the blockchain. +const ( + pubKeyTy scriptType = iota // Pay pubkey. + pubKeyHashTy // Pay pubkey hash. + scriptHashTy // Pay to script hash. + multiSigTy // Multi signature. + nonStandardTy // None of the above. +) + +// Script is the virtual machine that executes btcscripts. +type Script struct { + scripts [][]parsedOpcode + scriptidx int + scriptoff int + lastcodesep int + dstack Stack // data stack + astack Stack // alt stack + tx btcwire.MsgTx + txidx int + pver uint32 + condStack []int + numOps int + bip16 bool // treat execution as pay-to-script-hash + savedFirstStack [][]byte // stack from first script for bip16 scripts +} + +// isPubkey returns true if the script passed is a pubkey transaction, false +// otherwise. +func isPubkey(pops []parsedOpcode) bool { + return len(pops) == 2 && + pops[0].opcode.value > OP_FALSE && + pops[0].opcode.value <= OP_DATA_75 && + pops[1].opcode.value == OP_CHECKSIG +} + +// isPubkeyHash returns true if the script passed is a pubkey hash transaction, +// false otherwise. +func isPubkeyHash(pops []parsedOpcode) bool { + return len(pops) == 5 && + pops[0].opcode.value == OP_DUP && + pops[1].opcode.value == OP_HASH160 && + pops[2].opcode.value == OP_DATA_20 && + pops[3].opcode.value == OP_EQUALVERIFY && + pops[4].opcode.value == OP_CHECKSIG + +} + +// isScriptHash returns true if the script passed is a pay-to-script-hash (P2SH) +// transction, false otherwise. +func isScriptHash(pops []parsedOpcode) bool { + return len(pops) == 3 && + pops[0].opcode.value == OP_HASH160 && + pops[1].opcode.value == OP_DATA_20 && + pops[2].opcode.value == OP_EQUAL +} + +// isMultiSig returns true if the passed script is a multisig transaction, false +// otherwise. +func isMultiSig(pops []parsedOpcode) bool { + l := len(pops) + // absolute minimum is 1 pubkey so + // OP_1-16, pubkey, OP_1, OP_CHECK_MULTISIG + if l < 4 { + return false + } + if pops[0].opcode.value < OP_1 || + pops[0].opcode.value > OP_16 { + return false + } + if pops[l-2].opcode.value < OP_1 || + pops[l-2].opcode.value > OP_16 { + return false + } + if pops[l-1].opcode.value != OP_CHECK_MULTISIG { + return false + } + for _, pop := range pops[1 : l-2] { + // valid pubkeys are either 65 or 33 bytes + if len(pop.data) != 33 && + len(pop.data) != 65 { + return false + } + } + return true +} + +// isPushOnly returns true if the script only pushes data, false otherwise. +func isPushOnly(pops []parsedOpcode) bool { + // technically we cheat here, we don't look at opcodes + for _, pop := range pops { + // all opcodes up to OP_16 are data instructions. + if pop.opcode.value < OP_FALSE || + pop.opcode.value > OP_16 { + return false + } + } + return true +} + +// scriptType returns the type of the script being inspected from the known +// standard types. +func typeOfScript(pops []parsedOpcode) scriptType { + // XXX dubious optimisation: order these in order of popularity in the + // blockchain + if isPubkey(pops) { + return pubKeyTy + } else if isPubkeyHash(pops) { + return pubKeyHashTy + } else if isScriptHash(pops) { + return scriptHashTy + } else if isMultiSig(pops) { + return multiSigTy + } + return nonStandardTy + +} + +// parseScript preparses the script in bytes into a list of parsedOpcodes while +// applying a number of sanity checks. +func parseScript(script []byte) ([]parsedOpcode, error) { + retScript := []parsedOpcode{} + for i := 0; i < len(script); { + instr := script[i] + op, ok := opcodemap[instr] + if !ok { + return nil, StackErrInvalidOpcode + } + pop := parsedOpcode{opcode: op} + // parse data out of instruction. + switch { + case op.length == 1: + // no data, done here + i++ + case op.length > 1: + if len(script[i:]) < op.length { + return nil, StackErrShortScript + } + // slice out the data. + pop.data = script[i+1 : i+op.length] + i += op.length + case op.length < 0: + var err error + var l uint + off := i + 1 + switch op.length { + case -1: + l, err = scriptUInt8(script[off:]) + case -2: + l, err = scriptUInt16(script[off:]) + case -4: + l, err = scriptUInt32(script[off:]) + default: + return nil, fmt.Errorf("invalid opcode length %d", op.length) + } + + if err != nil { + return nil, err + } + off = i + 1 - op.length // beginning of data + if int(l) > len(script[off:]) { + return nil, StackErrShortScript + } + if l > MaxScriptElementSize { + return nil, StackErrElementTooBig + } + pop.data = script[off : off+int(l)] + i += 1 - op.length + int(l) + } + retScript = append(retScript, pop) + } + return retScript, nil +} + +// unparseScript reversed the action of parseScript and returns the +// parsedOpcodes as a list of bytes +func unparseScript(pops []parsedOpcode) []byte { + script := []byte{} + for _, pop := range pops { + script = append(script, pop.bytes()...) + } + return script +} + +// NewScript returns a new script engine for the provided tx and input idx with +// a signature script scriptSig and a pubkeyscript scriptPubKey. If bip16 is +// true then it will be treated as if the bip16 threshhold has passed and thus +// pay-to-script hash transactions will be fully validated. +func NewScript(scriptSig []byte, scriptPubKey []byte, txidx int, tx *btcwire.MsgTx, pver uint32, bip16 bool) (*Script, error) { + var m Script + scripts := [][]byte{scriptSig, scriptPubKey} + m.scripts = make([][]parsedOpcode, len(scripts)) + for i, scr := range scripts { + var err error + m.scripts[i], err = parseScript(scr) + if err != nil { + return nil, err + } + + // if the first scripts(s) are empty, must set the PC to the next script. + if len(scr) == 0 { + // yes this could end up setting to an invalid intial PC if all scripts were empty + m.scriptidx = i + 1 + } + } + + if bip16 && isScriptHash(m.scripts[1]) { + // if we are pay to scripthash then we only accept input + // scripts that push data + if !isPushOnly(m.scripts[0]) { + return nil, errors.New("pay to script hash with non " + + "pushonly input") + } + m.bip16 = true + } + + for i, _ := range tx.TxIn { + tx.TxIn[i].SignatureScript = []byte{} + } + m.tx = *tx + m.txidx = txidx + m.pver = pver + m.condStack = []int{OpCondTrue} + + return &m, nil +} + +// Execute will execturte all script in the script engine and return either nil +// for successful validation or an error if one occurred. +func (s *Script) Execute() (err error) { + done := false + for done != true { + log.Tracef("%v", newLogClosure(func() string { + dis, err := s.DisasmPC() + if err != nil { + return fmt.Sprintf("stepping (%v)", err) + } + return fmt.Sprintf("stepping %v", dis) + })) + + done, err = s.Step() + if err != nil { + return err + } + log.Tracef("%v", newLogClosure(func() string { + var dstr, astr string + + // if we're tracing, dump the stacks. + if s.dstack.Depth() != 0 { + dstr = "Stack\n" + spew.Sdump(s.dstack) + } + if s.astack.Depth() != 0 { + astr = "AltStack\n" + spew.Sdump(s.astack) + } + + return dstr + astr + })) + } + if s.dstack.Depth() < 1 { + return fmt.Errorf("stack empty at end of execution") + } + v, err := s.dstack.PopBool() + if err == nil && v == false { + // log interesting data. + log.Tracef("%v", func() string { + dis0, _ := s.DisasmScript(0) + dis1, _ := s.DisasmScript(1) + return fmt.Sprintf("script0: %s\n script1: %s", + dis0, dis1) + }) + err = StackErrScriptFailed + } + if err == nil && len(s.condStack) != 1 { + // conditional execution stack context left active + err = StackErrMissingEndif + } + + return err +} + +// Step will execute the next instruction and move the program counter to the +// next opcode in the script, or the next script if the curent has ended. Step +// will return true in the case that the last opcode was successfully executed. +// if an error is returned then the result of calling Step or any other method +// is undefined. +func (m *Script) Step() (done bool, err error) { + // verify that it is pointing to a valid script address + err = m.validPC() + if err != nil { + return + } + opcode := m.scripts[m.scriptidx][m.scriptoff] + + executeInstr := true + if m.condStack[0] != OpCondTrue { + // some opcodes still 'activate' if on the non-executing side + // of conditional execution + if opcode.conditional() { + executeInstr = true + } else { + executeInstr = false + } + } + if executeInstr { + err = opcode.exec(m) + if err != nil { + return + } + } + + // prepare for next instruction + m.scriptoff++ + if m.scriptoff >= len(m.scripts[m.scriptidx]) { + // should only be == from checks before + m.scriptoff = 0 + if m.scriptidx == 0 && m.bip16 { + m.savedFirstStack = m.GetStack() + } else if m.scriptidx == 1 && m.bip16 { + // Check for successful completion of script + v, err := m.dstack.PopBool() + if err != nil { + return false, err + } + if v == false { + return false, StackErrScriptFailed + } + // check that first element on stack is a bool + script := m.savedFirstStack[len(m.savedFirstStack)-1] + pops, err := parseScript(script) + if err != nil { + return false, err + } + m.scripts = append(m.scripts, pops) + // Set stack to be the stack from first script + // minus the script itself + m.SetStack(m.savedFirstStack[:len(m.savedFirstStack)-1]) + } + m.scriptidx++ + // there are zero length scripts in the wild + if m.scriptidx < len(m.scripts) && m.scriptoff >= len(m.scripts[m.scriptidx]) { + m.scriptidx++ + } + m.lastcodesep = 0 + if m.scriptidx >= len(m.scripts) { + done = true + } + } + return +} + +// curPC returns either the current script and offset, or an error if the +// position isn't valid. +func (m *Script) curPC() (script int, off int, err error) { + err = m.validPC() + if err != nil { + return 0, 0, err + } + return m.scriptidx, m.scriptoff, nil +} + +// validPC returns an error if the current script position is valid for +// execution, nil otherwise. +func (m *Script) validPC() error { + if m.scriptidx >= len(m.scripts) { + return fmt.Errorf("Past input scripts %v:%v %v:xxxx", m.scriptidx, m.scriptoff, len(m.scripts)) + } + if m.scriptoff >= len(m.scripts[m.scriptidx]) { + return fmt.Errorf("Past input scripts %v:%v %v:%04d", m.scriptidx, m.scriptoff, m.scriptidx, len(m.scripts[m.scriptidx])) + } + return nil +} + +// DisasmScript returns the disassembly string for the script at offset +// ``idx''. Where 0 is the scriptSig and 1 is the scriptPubKey. +func (m *Script) DisasmScript(idx int) (disstr string, err error) { + if idx >= len(m.scripts) { + return "", fmt.Errorf("Invalid script index") + } + for i := range m.scripts[idx] { + disstr = disstr + m.disasm(idx, i) + "\n" + } + return disstr, nil +} + +// DisasmPC returns the string for the disassembly of the opcode that will be +// next to execute when Step() is called. +func (m *Script) DisasmPC() (disstr string, err error) { + scriptidx, scriptoff, err := m.curPC() + if err != nil { + return "", err + } + return m.disasm(scriptidx, scriptoff), nil +} + +// disasm is a helper member to produce the output for DisasmPC and +// DisasmScript. It produces the opcode prefixed by the program counter at the +// provided position in the script. it does no error checking and leaves that +// to the caller to provide a valid offse. +func (m *Script) disasm(scriptidx int, scriptoff int) string { + return fmt.Sprintf("%02x:%04x: %s", scriptidx, scriptoff, + m.scripts[scriptidx][scriptoff].print(false)) +} + +// subScript will return the script since the last OP_CODESEPARATOR +func (s *Script) subScript() []parsedOpcode { + return s.scripts[s.scriptidx][s.lastcodesep:] +} + +// removeOpcode will remove any opcode matching ``opcode'' from the opcode +// stream in pkscript +func removeOpcode(pkscript []parsedOpcode, opcode byte) []parsedOpcode { + retScript := []parsedOpcode{} + for _, pop := range pkscript { + if pop.opcode.value != opcode { + retScript = append(retScript, pop) + } + } + return retScript +} + +// removeOpcodeByData will return the pkscript minus any opcodes that would +// push the data in ``data'' to the stack. +func removeOpcodeByData(pkscript []parsedOpcode, data []byte) []parsedOpcode { + retScript := []parsedOpcode{} + for _, pop := range pkscript { + if !bytes.Equal(pop.data, data) { + retScript = append(retScript, pop) + } + } + return retScript + +} + +// DisasmString formats a disassembled script for one line printing. +func DisasmString(buf []byte) (string, error) { + disbuf := "" + opcodes, err := parseScript(buf) + if err != nil { + return "", err + } + for _, pop := range opcodes { + disbuf += pop.print(true) + " " + } + if disbuf != "" { + disbuf = disbuf[:len(disbuf)-1] + } + return disbuf, nil +} + +// calcScriptHash will, given the a script and hashtype for the current +// scriptmachine, calculate the doubleSha256 hash of the transaction and +// script to be used for signature signing and verification. +func (s *Script) calcScriptHash(script []parsedOpcode, hashType byte) []byte { + + // remove all instances of OP_CODESEPARATOR still left in the script + script = removeOpcode(script, OP_CODESEPARATOR) + + // Make a deep copy of the transaction, zeroing out the script + // for all inputs that are not currently being processed. + txCopy := s.tx.Copy() + txidx := s.txidx + for i := range txCopy.TxIn { + var txIn btcwire.TxIn + txIn = *txCopy.TxIn[i] + txCopy.TxIn[i] = &txIn + if i == txidx { + txCopy.TxIn[txidx].SignatureScript = + unparseScript(script) + } else { + txCopy.TxIn[i].SignatureScript = []byte{} + } + } + // Default behaviour has all outputs set up. + for i := range txCopy.TxOut { + var txOut btcwire.TxOut + txOut = *txCopy.TxOut[i] + txCopy.TxOut[i] = &txOut + } + + switch hashType & 31 { + case SigHashNone: + txCopy.TxOut = txCopy.TxOut[0:0] // empty slice + for i := range txCopy.TxIn { + if i != txidx { + txCopy.TxIn[i].Sequence = 0 + } + } + case SigHashSingle: + // resize output array to up to and including current output + txCopy.TxOut = txCopy.TxOut[:txidx+1] + // all but current output get zeroed out + for i := 0; i < txidx; i++ { + txCopy.TxOut[i].Value = -1 + txCopy.TxOut[i].PkScript = []byte{} + } + // Sequence on all other inputs is 0, too. + for i := range txCopy.TxIn { + if i != txidx { + txCopy.TxIn[i].Sequence = 0 + } + } + default: + // XXX bitcoind treats undefined hashtypes like normal + // SigHashAll for purposes of hash generation. + fallthrough + case SigHashOld: + fallthrough + case SigHashAll: + // nothing special here + } + if hashType&SigHashAnyOneCanPay != 0 { + txCopy.TxIn = txCopy.TxIn[s.txidx : s.txidx+1] + txidx = 0 + } + + var wbuf bytes.Buffer + txCopy.BtcEncode(&wbuf, s.pver) + // Append LE 4 bytes hash type + binary.Write(&wbuf, binary.LittleEndian, uint32(hashType)) + + return btcwire.DoubleSha256(wbuf.Bytes()) +} + +// scriptUInt8 return the number stored in the first byte of a slice. +func scriptUInt8(script []byte) (uint, error) { + if len(script) <= 1 { + return 0, StackErrShortScript + } + return uint(script[0]), nil +} + +// scriptUInt16 returns the number stored in the next 2 bytes of a slice. +func scriptUInt16(script []byte) (uint, error) { + if len(script) <= 2 { + return 0, StackErrShortScript + } + // Yes this is little endian + return ((uint(script[1]) << 8) | uint(script[0])), nil +} + +// scriptUInt32 returns the number stored in the first 4 bytes of a slice. +func scriptUInt32(script []byte) (uint, error) { + if len(script) <= 4 { + return 0, StackErrShortScript + } + // Yes this is little endian + return ((uint(script[3]) << 24) | (uint(script[2]) << 16) | + (uint(script[1]) << 8) | uint(script[0])), nil +} + +// getStack returns the contents of stack as a byte array bottom up +func getStack(stack *Stack) [][]byte { + array := make([][]byte, stack.Depth()) + for i := range array { + // PeekByteArry can't fail due to overflow, already checked + array[len(array)-i-1], _ = + stack.PeekByteArray(i) + } + return array +} + +// setStack sets the stack to the contents of the array where the last item in +// the array is the top item in the stack. +func setStack(stack *Stack, data [][]byte) { + // This can not error. Only errors are for invalid arguments. + _ = stack.DropN(stack.Depth()) + + for i := range data { + stack.PushByteArray(data[i]) + } +} + +// GetStack returns the contents of the primary stack as an array. where the +// last item in the array is the top of the stack. +func (s *Script) GetStack() [][]byte { + return getStack(&s.dstack) +} + +// SetStack sets the contents of the primary stack to the contents of the +// provided array where the last item in the array will be the top of the stack. +func (s *Script) SetStack(data [][]byte) { + setStack(&s.dstack, data) +} + +// GetAltStack returns the contents of the primary stack as an array. where the +// last item in the array is the top of the stack. +func (s *Script) GetAltStack() [][]byte { + return getStack(&s.astack) +} + +// SetAltStack sets the contents of the primary stack to the contents of the +// provided array where the last item in the array will be the top of the stack. +func (s *Script) SetAltStack(data [][]byte) { + setStack(&s.astack, data) +} diff --git a/script_test.go b/script_test.go new file mode 100644 index 00000000..463344d8 --- /dev/null +++ b/script_test.go @@ -0,0 +1,1060 @@ +// Copyright (c) 2013 Conformal Systems LLC. +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcscript_test + +import ( + "bytes" + "github.com/conformal/btcscript" + "github.com/conformal/btcwire" + "testing" +) + +type txTest struct { + name string + tx *btcwire.MsgTx + pkScript []byte // output script of previous tx + idx int + bip16 bool + err error +} + +var txTests = []txTest{ + // tx 0437cd7f8525ceed2324359c2d0ba26006d92d85. the first tx in the + // blockchain that verifies signatures. + txTest{ + name: "CheckSig", + tx: &btcwire.MsgTx{ + Version: 1, + TxIn: []*btcwire.TxIn{ + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash([32]byte{ + 0xc9, 0x97, 0xa5, 0xe5, + 0x6e, 0x10, 0x41, 0x02, + 0xfa, 0x20, 0x9c, 0x6a, + 0x85, 0x2d, 0xd9, 0x06, + 0x60, 0xa2, 0x0b, 0x2d, + 0x9c, 0x35, 0x24, 0x23, + 0xed, 0xce, 0x25, 0x85, + 0x7f, 0xcd, 0x37, 0x04, + }), + Index: 0, + }, + SignatureScript: []uint8{ + btcscript.OP_DATA_71, + 0x30, 0x44, 0x02, 0x20, 0x4e, + 0x45, 0xe1, 0x69, 0x32, 0xb8, + 0xaf, 0x51, 0x49, 0x61, 0xa1, + 0xd3, 0xa1, 0xa2, 0x5f, 0xdf, + 0x3f, 0x4f, 0x77, 0x32, 0xe9, + 0xd6, 0x24, 0xc6, 0xc6, 0x15, + 0x48, 0xab, 0x5f, 0xb8, 0xcd, + 0x41, 0x02, 0x20, 0x18, 0x15, + 0x22, 0xec, 0x8e, 0xca, 0x07, + 0xde, 0x48, 0x60, 0xa4, 0xac, + 0xdd, 0x12, 0x90, 0x9d, 0x83, + 0x1c, 0xc5, 0x6c, 0xbb, 0xac, + 0x46, 0x22, 0x08, 0x22, 0x21, + 0xa8, 0x76, 0x8d, 0x1d, 0x09, + 0x01, + }, + + Sequence: 4294967295, + }, + }, + TxOut: []*btcwire.TxOut{ + &btcwire.TxOut{ + Value: 1000000000, + PkScript: []byte{ + btcscript.OP_DATA_65, + 0x04, 0xae, 0x1a, 0x62, 0xfe, + 0x09, 0xc5, 0xf5, 0x1b, 0x13, + 0x90, 0x5f, 0x07, 0xf0, 0x6b, + 0x99, 0xa2, 0xf7, 0x15, 0x9b, + 0x22, 0x25, 0xf3, 0x74, 0xcd, + 0x37, 0x8d, 0x71, 0x30, 0x2f, + 0xa2, 0x84, 0x14, 0xe7, 0xaa, + 0xb3, 0x73, 0x97, 0xf5, 0x54, + 0xa7, 0xdf, 0x5f, 0x14, 0x2c, + 0x21, 0xc1, 0xb7, 0x30, 0x3b, + 0x8a, 0x06, 0x26, 0xf1, 0xba, + 0xde, 0xd5, 0xc7, 0x2a, 0x70, + 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, + btcscript.OP_CHECKSIG, + }, + }, + &btcwire.TxOut{ + Value: 4000000000, + PkScript: []byte{ + btcscript.OP_DATA_65, + 0x04, 0x11, 0xdb, 0x93, 0xe1, + 0xdc, 0xdb, 0x8a, 0x01, 0x6b, + 0x49, 0x84, 0x0f, 0x8c, 0x53, + 0xbc, 0x1e, 0xb6, 0x8a, 0x38, + 0x2e, 0x97, 0xb1, 0x48, 0x2e, + 0xca, 0xd7, 0xb1, 0x48, 0xa6, + 0x90, 0x9a, 0x5c, 0xb2, 0xe0, + 0xea, 0xdd, 0xfb, 0x84, 0xcc, + 0xf9, 0x74, 0x44, 0x64, 0xf8, + 0x2e, 0x16, 0x0b, 0xfa, 0x9b, + 0x8b, 0x64, 0xf9, 0xd4, 0xc0, + 0x3f, 0x99, 0x9b, 0x86, 0x43, + 0xf6, 0x56, 0xb4, 0x12, 0xa3, + btcscript.OP_CHECKSIG, + }, + }, + }, + LockTime: 0, + }, + pkScript: []byte{ + btcscript.OP_DATA_65, + 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, + 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 0xb6, + 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 0xd7, + 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0, 0xea, + 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64, 0xf8, + 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, + 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, + 0x12, 0xa3, btcscript.OP_CHECKSIG, + }, + idx: 0, + }, + // Previous test with the value of one output changed. + txTest{ + name: "CheckSig Failure", + tx: &btcwire.MsgTx{ + Version: 1, + TxIn: []*btcwire.TxIn{ + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash([32]byte{ + 0xc9, 0x97, 0xa5, 0xe5, + 0x6e, 0x10, 0x41, 0x02, + 0xfa, 0x20, 0x9c, 0x6a, + 0x85, 0x2d, 0xd9, 0x06, + 0x60, 0xa2, 0x0b, 0x2d, + 0x9c, 0x35, 0x24, 0x23, + 0xed, 0xce, 0x25, 0x85, + 0x7f, 0xcd, 0x37, 0x04, + }), + Index: 0, + }, + SignatureScript: []uint8{ + btcscript.OP_DATA_71, + 0x30, 0x44, 0x02, 0x20, 0x4e, + 0x45, 0xe1, 0x69, 0x32, 0xb8, + 0xaf, 0x51, 0x49, 0x61, 0xa1, + 0xd3, 0xa1, 0xa2, 0x5f, 0xdf, + 0x3f, 0x4f, 0x77, 0x32, 0xe9, + 0xd6, 0x24, 0xc6, 0xc6, 0x15, + 0x48, 0xab, 0x5f, 0xb8, 0xcd, + 0x41, 0x02, 0x20, 0x18, 0x15, + 0x22, 0xec, 0x8e, 0xca, 0x07, + 0xde, 0x48, 0x60, 0xa4, 0xac, + 0xdd, 0x12, 0x90, 0x9d, 0x83, + 0x1c, 0xc5, 0x6c, 0xbb, 0xac, + 0x46, 0x22, 0x08, 0x22, 0x21, + 0xa8, 0x76, 0x8d, 0x1d, 0x09, + 0x01, + }, + + Sequence: 4294967295, + }, + }, + TxOut: []*btcwire.TxOut{ + &btcwire.TxOut{ + Value: 1000000000, + PkScript: []byte{ + btcscript.OP_DATA_65, + 0x04, 0xae, 0x1a, 0x62, 0xfe, + 0x09, 0xc5, 0xf5, 0x1b, 0x13, + 0x90, 0x5f, 0x07, 0xf0, 0x6b, + 0x99, 0xa2, 0xf7, 0x15, 0x9b, + 0x22, 0x25, 0xf3, 0x74, 0xcd, + 0x37, 0x8d, 0x71, 0x30, 0x2f, + 0xa2, 0x84, 0x14, 0xe7, 0xaa, + 0xb3, 0x73, 0x97, 0xf5, 0x54, + 0xa7, 0xdf, 0x5f, 0x14, 0x2c, + 0x21, 0xc1, 0xb7, 0x30, 0x3b, + 0x8a, 0x06, 0x26, 0xf1, 0xba, + 0xde, 0xd5, 0xc7, 0x2a, 0x70, + 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, + btcscript.OP_CHECKSIG, + }, + }, + &btcwire.TxOut{ + Value: 5000000000, + PkScript: []byte{ + btcscript.OP_DATA_65, + 0x04, 0x11, 0xdb, 0x93, 0xe1, + 0xdc, 0xdb, 0x8a, 0x01, 0x6b, + 0x49, 0x84, 0x0f, 0x8c, 0x53, + 0xbc, 0x1e, 0xb6, 0x8a, 0x38, + 0x2e, 0x97, 0xb1, 0x48, 0x2e, + 0xca, 0xd7, 0xb1, 0x48, 0xa6, + 0x90, 0x9a, 0x5c, 0xb2, 0xe0, + 0xea, 0xdd, 0xfb, 0x84, 0xcc, + 0xf9, 0x74, 0x44, 0x64, 0xf8, + 0x2e, 0x16, 0x0b, 0xfa, 0x9b, + 0x8b, 0x64, 0xf9, 0xd4, 0xc0, + 0x3f, 0x99, 0x9b, 0x86, 0x43, + 0xf6, 0x56, 0xb4, 0x12, 0xa3, + btcscript.OP_CHECKSIG, + }, + }, + }, + LockTime: 0, + }, + pkScript: []byte{ + btcscript.OP_DATA_65, + 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, + 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 0xb6, + 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 0xd7, + 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0, 0xea, + 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64, 0xf8, + 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, + 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, + 0x12, 0xa3, btcscript.OP_CHECKSIG, + }, + idx: 0, + err: btcscript.StackErrScriptFailed, + }, + // tx 599e47a8114fe098103663029548811d2651991b62397e057f0c863c2bc9f9ea + // uses checksig with SigHashNone. + txTest{ + name: "CheckSigHashNone", + tx: &btcwire.MsgTx{ + Version: 1, + TxIn: []*btcwire.TxIn{ + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash([32]byte{ + 0x5f, 0x38, 0x6c, 0x8a, + 0x38, 0x42, 0xc9, 0xa9, + 0xdc, 0xfa, 0x9b, 0x78, + 0xbe, 0x78, 0x5a, 0x40, + 0xa7, 0xbd, 0xa0, 0x8b, + 0x64, 0x64, 0x6b, 0xe3, + 0x65, 0x43, 0x01, 0xea, + 0xcc, 0xfc, 0x8d, 0x5e, + }), + Index: 1, + }, + SignatureScript: []byte{ + btcscript.OP_DATA_71, + 0x30, 0x44, 0x02, 0x20, 0xbb, + 0x4f, 0xbc, 0x49, 0x5a, 0xa2, + 0x3b, 0xab, 0xb2, 0xc2, 0xbe, + 0x4e, 0x3f, 0xb4, 0xa5, 0xdf, + 0xfe, 0xfe, 0x20, 0xc8, 0xef, + 0xf5, 0x94, 0x0f, 0x13, 0x56, + 0x49, 0xc3, 0xea, 0x96, 0x44, + 0x4a, 0x02, 0x20, 0x04, 0xaf, + 0xcd, 0xa9, 0x66, 0xc8, 0x07, + 0xbb, 0x97, 0x62, 0x2d, 0x3e, + 0xef, 0xea, 0x82, 0x8f, 0x62, + 0x3a, 0xf3, 0x06, 0xef, 0x2b, + 0x75, 0x67, 0x82, 0xee, 0x6f, + 0x8a, 0x22, 0xa9, 0x59, 0xa2, + 0x02, + btcscript.OP_DATA_65, + 0x04, 0xf1, 0x93, 0x9a, 0xe6, + 0xb0, 0x1e, 0x84, 0x9b, 0xf0, + 0x5d, 0x0e, 0xd5, 0x1f, 0xd5, + 0xb9, 0x2b, 0x79, 0xa0, 0xe3, + 0x13, 0xe3, 0xf3, 0x89, 0xc7, + 0x26, 0xf1, 0x1f, 0xa3, 0xe1, + 0x44, 0xd9, 0x22, 0x7b, 0x07, + 0xe8, 0xa8, 0x7c, 0x0e, 0xe3, + 0x63, 0x72, 0xe9, 0x67, 0xe0, + 0x90, 0xd1, 0x1b, 0x77, 0x77, + 0x07, 0xaa, 0x73, 0xef, 0xac, + 0xab, 0xff, 0xff, 0xa2, 0x85, + 0xc0, 0x0b, 0x36, 0x22, 0xd6, + }, + Sequence: 4294967295, + }, + }, + TxOut: []*btcwire.TxOut{ + &btcwire.TxOut{ + Value: 1000000, + PkScript: []byte{ + btcscript.OP_DUP, + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0x66, 0x0d, 0x4e, 0xf3, 0xa7, + 0x43, 0xe3, 0xe6, 0x96, 0xad, + 0x99, 0x03, 0x64, 0xe5, 0x55, + 0xc2, 0x71, 0xad, 0x50, 0x4b, + btcscript.OP_EQUALVERIFY, + btcscript.OP_CHECKSIG, + }, + }, + &btcwire.TxOut{ + Value: 29913632, + PkScript: []byte{ + btcscript.OP_DUP, + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0x21, 0xc4, 0x3c, 0xe4, 0x00, + 0x90, 0x13, 0x12, 0xa6, 0x03, + 0xe4, 0x20, 0x7a, 0xad, 0xfd, + 0x74, 0x2b, 0xe8, 0xe7, 0xda, + btcscript.OP_EQUALVERIFY, + btcscript.OP_CHECKSIG, + }, + }, + }, + LockTime: 0, + }, + pkScript: []byte{ + btcscript.OP_DUP, + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0x21, 0xc4, 0x3c, 0xe4, 0x00, 0x90, 0x13, 0x12, 0xa6, + 0x03, 0xe4, 0x20, 0x7a, 0xad, 0xfd, 0x74, 0x2b, 0xe8, + 0xe7, 0xda, + btcscript.OP_EQUALVERIFY, + btcscript.OP_CHECKSIG, + }, + idx: 0, + bip16: true, // after threshold + }, + // tx 51bf528ecf3c161e7c021224197dbe84f9a8564212f6207baa014c01a1668e1e + // first instance of an AnyoneCanPay signature in the blockchain + txTest{ + name: "CheckSigHashAnyoneCanPay", + tx: &btcwire.MsgTx{ + Version: 1, + TxIn: []*btcwire.TxIn{ + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash([32]byte{ + 0xf6, 0x04, 0x4c, 0x0a, + 0xd4, 0x85, 0xf6, 0x33, + 0xb4, 0x1f, 0x97, 0xd0, + 0xd7, 0x93, 0xeb, 0x28, + 0x37, 0xae, 0x40, 0xf7, + 0x38, 0xff, 0x6d, 0x5f, + 0x50, 0xfd, 0xfd, 0x10, + 0x52, 0x8c, 0x1d, 0x76, + }), + Index: 1, + }, + SignatureScript: []byte{ + btcscript.OP_DATA_72, + 0x30, 0x45, 0x02, 0x20, 0x58, + 0x53, 0xc7, 0xf1, 0x39, 0x57, + 0x85, 0xbf, 0xab, 0xb0, 0x3c, + 0x57, 0xe9, 0x62, 0xeb, 0x07, + 0x6f, 0xf2, 0x4d, 0x8e, 0x4e, + 0x57, 0x3b, 0x04, 0xdb, 0x13, + 0xb4, 0x5e, 0xd3, 0xed, 0x6e, + 0xe2, 0x02, 0x21, 0x00, 0x9d, + 0xc8, 0x2a, 0xe4, 0x3b, 0xe9, + 0xd4, 0xb1, 0xfe, 0x28, 0x47, + 0x75, 0x4e, 0x1d, 0x36, 0xda, + 0xd4, 0x8b, 0xa8, 0x01, 0x81, + 0x7d, 0x48, 0x5d, 0xc5, 0x29, + 0xaf, 0xc5, 0x16, 0xc2, 0xdd, + 0xb4, 0x81, + btcscript.OP_DATA_33, + 0x03, 0x05, 0x58, 0x49, 0x80, + 0x36, 0x7b, 0x32, 0x1f, 0xad, + 0x7f, 0x1c, 0x1f, 0x4d, 0x5d, + 0x72, 0x3d, 0x0a, 0xc8, 0x0c, + 0x1d, 0x80, 0xc8, 0xba, 0x12, + 0x34, 0x39, 0x65, 0xb4, 0x83, + 0x64, 0x53, 0x7a, + }, + Sequence: 4294967295, + }, + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash([32]byte{ + 0x9c, 0x6a, 0xf0, 0xdf, + 0x66, 0x69, 0xbc, 0xde, + 0xd1, 0x9e, 0x31, 0x7e, + 0x25, 0xbe, 0xbc, 0x8c, + 0x78, 0xe4, 0x8d, 0xf8, + 0xae, 0x1f, 0xe0, 0x2a, + 0x7f, 0x03, 0x08, 0x18, + 0xe7, 0x1e, 0xcd, 0x40, + }), + Index: 1, + }, + SignatureScript: []byte{ + btcscript.OP_DATA_73, + 0x30, 0x46, 0x02, 0x21, 0x00, + 0x82, 0x69, 0xc9, 0xd7, 0xba, + 0x0a, 0x7e, 0x73, 0x0d, 0xd1, + 0x6f, 0x40, 0x82, 0xd2, 0x9e, + 0x36, 0x84, 0xfb, 0x74, 0x63, + 0xba, 0x06, 0x4f, 0xd0, 0x93, + 0xaf, 0xc1, 0x70, 0xad, 0x6e, + 0x03, 0x88, 0x02, 0x21, 0x00, + 0xbc, 0x6d, 0x76, 0x37, 0x39, + 0x16, 0xa3, 0xff, 0x6e, 0xe4, + 0x1b, 0x2c, 0x75, 0x20, 0x01, + 0xfd, 0xa3, 0xc9, 0xe0, 0x48, + 0xbc, 0xff, 0x0d, 0x81, 0xd0, + 0x5b, 0x39, 0xff, 0x0f, 0x42, + 0x17, 0xb2, 0x81, + btcscript.OP_DATA_33, + 0x03, 0xaa, 0xe3, 0x03, 0xd8, + 0x25, 0x42, 0x15, 0x45, 0xc5, + 0xbc, 0x7c, 0xcd, 0x5a, 0xc8, + 0x7d, 0xd5, 0xad, 0xd3, 0xbc, + 0xc3, 0xa4, 0x32, 0xba, 0x7a, + 0xa2, 0xf2, 0x66, 0x16, 0x99, + 0xf9, 0xf6, 0x59, + }, + Sequence: 4294967295, + }, + }, + TxOut: []*btcwire.TxOut{ + &btcwire.TxOut{ + Value: 300000, + PkScript: []byte{ + btcscript.OP_DUP, + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0x5c, 0x11, 0xf9, 0x17, 0x88, + 0x3b, 0x92, 0x7e, 0xef, 0x77, + 0xdc, 0x57, 0x70, 0x7a, 0xeb, + 0x85, 0x3f, 0x6d, 0x38, 0x94, + btcscript.OP_EQUALVERIFY, + btcscript.OP_CHECKSIG, + }, + }, + }, + LockTime: 0, + }, + pkScript: []byte{ + btcscript.OP_DUP, + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0x85, 0x51, 0xe4, 0x8a, 0x53, 0xde, 0xcd, 0x1c, 0xfc, + 0x63, 0x07, 0x9a, 0x45, 0x81, 0xbc, 0xcc, 0xfa, 0xd1, + 0xa9, 0x3c, + btcscript.OP_EQUALVERIFY, + btcscript.OP_CHECKSIG, + }, + idx: 0, + bip16: true, // after threshold + }, + // tx 6d36bc17e947ce00bb6f12f8e7a56a1585c5a36188ffa2b05e10b4743273a74b + // Uses OP_CODESEPARATOR and OP_CHECKMULTISIG + txTest{ + name: "CheckMultiSig", + tx: &btcwire.MsgTx{ + Version: 1, + TxIn: []*btcwire.TxIn{ + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash([32]byte{ + 0x37, 0xb1, 0x7d, 0x76, + 0x38, 0x51, 0xcd, 0x1a, + 0xb0, 0x4a, 0x42, 0x44, + 0x63, 0xd4, 0x13, 0xc4, + 0xee, 0x5c, 0xf6, 0x13, + 0x04, 0xc7, 0xfd, 0x76, + 0x97, 0x7b, 0xea, 0x7f, + 0xce, 0x07, 0x57, 0x05, + }), + Index: 0, + }, + SignatureScript: []byte{ + btcscript.OP_DATA_71, + 0x30, 0x44, 0x02, 0x20, 0x02, + 0xdb, 0xe4, 0xb5, 0xa2, 0xfb, + 0xb5, 0x21, 0xe4, 0xdc, 0x5f, + 0xbe, 0xc7, 0x5f, 0xd9, 0x60, + 0x65, 0x1a, 0x27, 0x54, 0xb0, + 0x3d, 0x08, 0x71, 0xb8, 0xc9, + 0x65, 0x46, 0x9b, 0xe5, 0x0f, + 0xa7, 0x02, 0x20, 0x6d, 0x97, + 0x42, 0x1f, 0xb7, 0xea, 0x93, + 0x59, 0xb6, 0x3e, 0x48, 0xc2, + 0x10, 0x82, 0x23, 0x28, 0x4b, + 0x9a, 0x71, 0x56, 0x0b, 0xd8, + 0x18, 0x24, 0x69, 0xb9, 0x03, + 0x92, 0x28, 0xd7, 0xb3, 0xd7, + 0x01, 0x21, 0x02, 0x95, 0xbf, + 0x72, 0x71, 0x11, 0xac, 0xde, + 0xab, 0x87, 0x78, 0x28, 0x4f, + 0x02, 0xb7, 0x68, 0xd1, 0xe2, + 0x1a, 0xcb, 0xcb, 0xae, 0x42, + }, + Sequence: 4294967295, + }, + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash([32]byte{ + 0x37, 0xb1, 0x7d, 0x76, + 0x38, 0x51, 0xcd, 0x1a, + 0xb0, 0x4a, 0x42, 0x44, + 0x63, 0xd4, 0x13, 0xc4, + 0xee, 0x5c, 0xf6, 0x13, + 0x04, 0xc7, 0xfd, 0x76, + 0x97, 0x7b, 0xea, 0x7f, + 0xce, 0x07, 0x57, 0x05, + }), + Index: 1, + }, + SignatureScript: []uint8{ + btcscript.OP_FALSE, + btcscript.OP_DATA_72, + 0x30, 0x45, 0x02, 0x20, 0x10, + 0x6a, 0x3e, 0x4e, 0xf0, 0xb5, + 0x1b, 0x76, 0x4a, 0x28, 0x87, + 0x22, 0x62, 0xff, 0xef, 0x55, + 0x84, 0x65, 0x14, 0xda, 0xcb, + 0xdc, 0xbb, 0xdd, 0x65, 0x2c, + 0x84, 0x9d, 0x39, 0x5b, 0x43, + 0x84, 0x02, 0x21, 0x00, 0xe0, + 0x3a, 0xe5, 0x54, 0xc3, 0xcb, + 0xb4, 0x06, 0x00, 0xd3, 0x1d, + 0xd4, 0x6f, 0xc3, 0x3f, 0x25, + 0xe4, 0x7b, 0xf8, 0x52, 0x5b, + 0x1f, 0xe0, 0x72, 0x82, 0xe3, + 0xb6, 0xec, 0xb5, 0xf3, 0xbb, + 0x28, 0x01, + btcscript.OP_CODESEPARATOR, + btcscript.OP_TRUE, + btcscript.OP_DATA_33, + 0x02, 0x32, 0xab, 0xdc, 0x89, + 0x3e, 0x7f, 0x06, 0x31, 0x36, + 0x4d, 0x7f, 0xd0, 0x1c, 0xb3, + 0x3d, 0x24, 0xda, 0x45, 0x32, + 0x9a, 0x00, 0x35, 0x7b, 0x3a, + 0x78, 0x86, 0x21, 0x1a, 0xb4, + 0x14, 0xd5, 0x5a, + btcscript.OP_TRUE, + btcscript.OP_CHECK_MULTISIG, + }, + Sequence: 4294967295, + }, + }, + TxOut: []*btcwire.TxOut{ + &btcwire.TxOut{ + Value: 4800000, + PkScript: []byte{ + btcscript.OP_DUP, + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0x0d, 0x77, 0x13, 0x64, 0x9f, + 0x9a, 0x06, 0x78, 0xf4, 0xe8, + 0x80, 0xb4, 0x0f, 0x86, 0xb9, + 0x32, 0x89, 0xd1, 0xbb, 0x27, + btcscript.OP_EQUALVERIFY, + btcscript.OP_CHECKSIG, + }, + }, + }, + LockTime: 0, + }, + // This is a very weird script... + pkScript: []byte{ + btcscript.OP_DATA_20, + 0x2a, 0x9b, 0xc5, 0x44, 0x7d, 0x66, 0x4c, 0x1d, 0x01, + 0x41, 0x39, 0x2a, 0x84, 0x2d, 0x23, 0xdb, 0xa4, 0x5c, + 0x4f, 0x13, + btcscript.OP_NOP2, btcscript.OP_DROP, + }, + idx: 1, + bip16: false, + }, + // same as previous but with one byte changed to make signature fail + txTest{ + name: "CheckMultiSig fail", + tx: &btcwire.MsgTx{ + Version: 1, + TxIn: []*btcwire.TxIn{ + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash([32]byte{ + 0x37, 0xb1, 0x7d, 0x76, + 0x38, 0x51, 0xcd, 0x1a, + 0xb0, 0x4a, 0x42, 0x44, + 0x63, 0xd4, 0x13, 0xc4, + 0xee, 0x5c, 0xf6, 0x13, + 0x04, 0xc7, 0xfd, 0x76, + 0x97, 0x7b, 0xea, 0x7f, + 0xce, 0x07, 0x57, 0x05, + }), + Index: 0, + }, + SignatureScript: []byte{ + btcscript.OP_DATA_71, + 0x30, 0x44, 0x02, 0x20, 0x02, + 0xdb, 0xe4, 0xb5, 0xa2, 0xfb, + 0xb5, 0x21, 0xe4, 0xdc, 0x5f, + 0xbe, 0xc7, 0x5f, 0xd9, 0x60, + 0x65, 0x1a, 0x27, 0x54, 0xb0, + 0x3d, 0x08, 0x71, 0xb8, 0xc9, + 0x65, 0x46, 0x9b, 0xe5, 0x0f, + 0xa7, 0x02, 0x20, 0x6d, 0x97, + 0x42, 0x1f, 0xb7, 0xea, 0x93, + 0x59, 0xb6, 0x3e, 0x48, 0xc2, + 0x10, 0x82, 0x23, 0x28, 0x4b, + 0x9a, 0x71, 0x56, 0x0b, 0xd8, + 0x18, 0x24, 0x69, 0xb9, 0x03, + 0x92, 0x28, 0xd7, 0xb3, 0xd7, + 0x01, 0x21, 0x02, 0x95, 0xbf, + 0x72, 0x71, 0x11, 0xac, 0xde, + 0xab, 0x87, 0x78, 0x28, 0x4f, + 0x02, 0xb7, 0x68, 0xd1, 0xe2, + 0x1a, 0xcb, 0xcb, 0xae, 0x42, + }, + Sequence: 4294967295, + }, + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash([32]byte{ + 0x37, 0xb1, 0x7d, 0x76, + 0x38, 0x51, 0xcd, 0x1a, + 0xb0, 0x4a, 0x42, 0x44, + 0x63, 0xd4, 0x13, 0xc4, + 0xee, 0x5c, 0xf6, 0x13, + 0x04, 0xc7, 0xfd, 0x76, + 0x97, 0x7b, 0xea, 0x7f, + 0xce, 0x07, 0x57, 0x05, + }), + Index: 1, + }, + SignatureScript: []uint8{ + btcscript.OP_FALSE, + btcscript.OP_DATA_72, + 0x30, 0x45, 0x02, 0x20, 0x10, + 0x6a, 0x3e, 0x4e, 0xf0, 0xb5, + 0x1b, 0x76, 0x4a, 0x28, 0x87, + 0x22, 0x62, 0xff, 0xef, 0x55, + 0x84, 0x65, 0x14, 0xda, 0xcb, + 0xdc, 0xbb, 0xdd, 0x65, 0x2c, + 0x84, 0x9d, 0x39, 0x5b, 0x43, + 0x84, 0x02, 0x21, 0x00, 0xe0, + 0x3a, 0xe5, 0x54, 0xc3, 0xcb, + 0xb4, 0x06, 0x00, 0xd3, 0x1d, + 0xd4, 0x6f, 0xc3, 0x3f, 0x25, + 0xe4, 0x7b, 0xf8, 0x52, 0x5b, + 0x1f, 0xe0, 0x72, 0x82, 0xe3, + 0xb6, 0xec, 0xb5, 0xf3, 0xbb, + 0x28, 0x01, + btcscript.OP_CODESEPARATOR, + btcscript.OP_TRUE, + btcscript.OP_DATA_33, + 0x02, 0x32, 0xab, 0xdc, 0x89, + 0x3e, 0x7f, 0x06, 0x31, 0x36, + 0x4d, 0x7f, 0xd0, 0x1c, 0xb3, + 0x3d, 0x24, 0xda, 0x45, 0x32, + 0x9a, 0x00, 0x35, 0x7b, 0x3a, + 0x78, 0x86, 0x21, 0x1a, 0xb4, + 0x14, 0xd5, 0x5a, + btcscript.OP_TRUE, + btcscript.OP_CHECK_MULTISIG, + }, + Sequence: 4294967295, + }, + }, + TxOut: []*btcwire.TxOut{ + &btcwire.TxOut{ + Value: 5800000, + PkScript: []byte{ + btcscript.OP_DUP, + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0x0d, 0x77, 0x13, 0x64, 0x9f, + 0x9a, 0x06, 0x78, 0xf4, 0xe8, + 0x80, 0xb4, 0x0f, 0x86, 0xb9, + 0x32, 0x89, 0xd1, 0xbb, 0x27, + btcscript.OP_EQUALVERIFY, + btcscript.OP_CHECKSIG, + }, + }, + }, + LockTime: 0, + }, + // This is a very weird script... + pkScript: []byte{ + btcscript.OP_DATA_20, + 0x2a, 0x9b, 0xc5, 0x44, 0x7d, 0x66, 0x4c, 0x1d, 0x01, + 0x41, 0x39, 0x2a, 0x84, 0x2d, 0x23, 0xdb, 0xa4, 0x5c, + 0x4f, 0x13, + btcscript.OP_NOP2, btcscript.OP_DROP, + }, + idx: 1, + bip16: false, + err: btcscript.StackErrScriptFailed, + }, + // tx e5779b9e78f9650debc2893fd9636d827b26b4ddfa6a8172fe8708c924f5c39d + // First P2SH transaction in the blockchain + txTest{ + name: "P2SH", + tx: &btcwire.MsgTx{ + Version: 1, + TxIn: []*btcwire.TxIn{ + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash([32]byte{ + 0x6d, 0x58, 0xf8, 0xa3, + 0xaa, 0x43, 0x0b, 0x84, + 0x78, 0x52, 0x3a, 0x65, + 0xc2, 0x03, 0xa2, 0x7b, + 0xb8, 0x81, 0x17, 0x8c, + 0xb1, 0x23, 0x13, 0xaf, + 0xde, 0x29, 0xf9, 0x2e, + 0xd7, 0x56, 0xaa, 0x7e, + }), + Index: 0, + }, + SignatureScript: []byte{ + btcscript.OP_DATA_2, + // OP_3 OP_7 + 0x53, 0x57, + }, + Sequence: 4294967295, + }, + }, + TxOut: []*btcwire.TxOut{ + &btcwire.TxOut{ + Value: 1000000, + PkScript: []byte{ + btcscript.OP_DUP, + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0x5b, 0x69, 0xd8, 0xb9, 0xdf, + 0xa6, 0xe4, 0x12, 0x26, 0x47, + 0xe1, 0x79, 0x4e, 0xaa, 0x3b, + 0xfc, 0x11, 0x1f, 0x70, 0xef, + btcscript.OP_EQUALVERIFY, + btcscript.OP_CHECKSIG, + }, + }, + }, + LockTime: 0, + }, + pkScript: []byte{ + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0x43, 0x3e, 0xc2, 0xac, 0x1f, 0xfa, 0x1b, 0x7b, 0x7d, + 0x02, 0x7f, 0x56, 0x45, 0x29, 0xc5, 0x71, 0x97, 0xf9, + 0xae, 0x88, + btcscript.OP_EQUAL, + }, + idx: 0, + bip16: true, + }, +} + +// Test a number of tx from the blockchain to test otherwise difficult to test +// opcodes (i.e. those that involve signatures). Being from the blockchain, +// these transactions are known good. +// TODO(oga) For signatures we currently do not test SigHashSingle because +// nothing in the blockchain that we have yet seen uses them, making it hard +// to confirm we implemented the spec correctly. +func testTx(t *testing.T, test txTest) { + engine, err := btcscript.NewScript( + test.tx.TxIn[test.idx].SignatureScript, test.pkScript, + test.idx, test.tx, 70001, test.bip16) + if err != nil { + t.Errorf("Failed to parse %s: %v", test.name, err) + return + } + + err = engine.Execute() + if err != nil { + if err != test.err { + t.Errorf("Failed to validate %s tx: %v expected %v", + test.name, err, test.err) + } + return + } + if test.err != nil { + t.Errorf("%s: expected failure: %v, succeeded", test.name, + test.err) + } +} + +func TestTX(t *testing.T) { + for i := range txTests { + testTx(t, txTests[i]) + } +} + +type removeOpcodeTest struct { + name string + before []byte + remove byte + err error + after []byte +} + +var removeOpcodeTests = []removeOpcodeTest{ + // Nothing to remove. + removeOpcodeTest{ + name: "nothing to remove", + before: []byte{btcscript.OP_NOP}, + remove: btcscript.OP_CODESEPARATOR, + after: []byte{btcscript.OP_NOP}, + }, + // Test basic opcode removal + removeOpcodeTest{ + name: "codeseparator 1", + before: []byte{btcscript.OP_NOP, btcscript.OP_CODESEPARATOR, + btcscript.OP_TRUE}, + remove: btcscript.OP_CODESEPARATOR, + after: []byte{btcscript.OP_NOP, btcscript.OP_TRUE}, + }, + // The opcode in question is actually part of the data in a previous + // opcode + removeOpcodeTest{ + name: "codeseparator by coincidence", + before: []byte{btcscript.OP_NOP, btcscript.OP_DATA_1, btcscript.OP_CODESEPARATOR, + btcscript.OP_TRUE}, + remove: btcscript.OP_CODESEPARATOR, + after: []byte{btcscript.OP_NOP, btcscript.OP_DATA_1, btcscript.OP_CODESEPARATOR, + btcscript.OP_TRUE}, + }, + removeOpcodeTest{ + name: "invalid opcode", + before: []byte{186}, + remove: btcscript.OP_CODESEPARATOR, + err: btcscript.StackErrInvalidOpcode, + }, + removeOpcodeTest{ + name: "invalid length (insruction)", + before: []byte{btcscript.OP_PUSHDATA1}, + remove: btcscript.OP_CODESEPARATOR, + err: btcscript.StackErrShortScript, + }, + removeOpcodeTest{ + name: "invalid length (data)", + before: []byte{btcscript.OP_PUSHDATA1, 255, 254}, + remove: btcscript.OP_CODESEPARATOR, + err: btcscript.StackErrShortScript, + }, +} + +func testRemoveOpcode(t *testing.T, test *removeOpcodeTest) { + result, err := btcscript.TstRemoveOpcode(test.before, test.remove) + if test.err != nil { + if err != test.err { + t.Errorf("%s: got unexpected error. exp: \"%v\" "+ + "got: \"%v\"", test.name, test.err, err) + } + return + } + if err != nil { + t.Errorf("%s: unexpected failure: \"%v\"", test.name, err) + return + } + if !bytes.Equal(test.after, result) { + t.Errorf("%s: value does not equal expected: exp: \"%v\""+ + " got: \"%v\"", test.name, test.after, result) + } +} + +func TestRemoveOpcodes(t *testing.T) { + for i := range removeOpcodeTests { + testRemoveOpcode(t, &removeOpcodeTests[i]) + } +} + +type removeOpcodeByDataTest struct { + name string + before []byte + remove []byte + err error + after []byte +} + +var removeOpcodeByDataTests = []removeOpcodeByDataTest{ + removeOpcodeByDataTest{ + name: "nothing to do", + before: []byte{btcscript.OP_NOP}, + remove: []byte{1, 2, 3, 4}, + after: []byte{btcscript.OP_NOP}, + }, + removeOpcodeByDataTest{ + name: "simple case", + before: []byte{btcscript.OP_DATA_4, 1, 2, 3, 4}, + remove: []byte{1, 2, 3, 4}, + after: []byte{}, + }, + removeOpcodeByDataTest{ + name: "simple case (miss)", + before: []byte{btcscript.OP_DATA_4, 1, 2, 3, 4}, + remove: []byte{1, 2, 3, 5}, + after: []byte{btcscript.OP_DATA_4, 1, 2, 3, 4}, + }, + removeOpcodeByDataTest{ + name: "simple case (pushdata1)", + before: []byte{btcscript.OP_PUSHDATA1, 4, 1, 2, 3, 4}, + remove: []byte{1, 2, 3, 4}, + after: []byte{}, + }, + removeOpcodeByDataTest{ + name: "simple case (pushdata1 miss)", + before: []byte{btcscript.OP_PUSHDATA1, 4, 1, 2, 3, 4}, + remove: []byte{1, 2, 3, 5}, + after: []byte{btcscript.OP_PUSHDATA1, 4, 1, 2, 3, 4}, + }, + removeOpcodeByDataTest{ + name: "simple case (pushdata2)", + before: []byte{btcscript.OP_PUSHDATA2, 4, 0, 1, 2, 3, 4}, + remove: []byte{1, 2, 3, 4}, + after: []byte{}, + }, + removeOpcodeByDataTest{ + name: "simple case (pushdata2 miss)", + before: []byte{btcscript.OP_PUSHDATA2, 4, 0, 1, 2, 3, 4}, + remove: []byte{1, 2, 3, 5}, + after: []byte{btcscript.OP_PUSHDATA2, 4, 0, 1, 2, 3, 4}, + }, + removeOpcodeByDataTest{ + name: "simple case (pushdata4)", + before: []byte{btcscript.OP_PUSHDATA4, 4, 0, 0, 0, 1, 2, 3, 4}, + remove: []byte{1, 2, 3, 4}, + after: []byte{}, + }, + removeOpcodeByDataTest{ + name: "simple case (pushdata4 miss)", + before: []byte{btcscript.OP_PUSHDATA4, 4, 0, 0, 0, 1, 2, 3, 4}, + remove: []byte{1, 2, 3, 4, 5}, + after: []byte{btcscript.OP_PUSHDATA4, 4, 0, 0, 0, 1, 2, 3, 4}, + }, + removeOpcodeByDataTest{ + name: "invalid opcode ", + before: []byte{187}, + remove: []byte{1, 2, 3, 4}, + err: btcscript.StackErrInvalidOpcode, + }, + removeOpcodeByDataTest{ + name: "invalid length (instruction)", + before: []byte{btcscript.OP_PUSHDATA1}, + remove: []byte{1, 2, 3, 4}, + err: btcscript.StackErrShortScript, + }, + removeOpcodeByDataTest{ + name: "invalid length (data)", + before: []byte{btcscript.OP_PUSHDATA1, 255, 254}, + remove: []byte{1, 2, 3, 4}, + err: btcscript.StackErrShortScript, + }, +} + +func testRemoveOpcodeByData(t *testing.T, test *removeOpcodeByDataTest) { + result, err := btcscript.TstRemoveOpcodeByData(test.before, + test.remove) + if test.err != nil { + if err != test.err { + t.Errorf("%s: got unexpected error. exp: \"%v\" "+ + "got: \"%v\"", test.name, test.err, err) + } + return + } + if err != nil { + t.Errorf("%s: unexpected failure: \"%v\"", test.name, err) + return + } + if !bytes.Equal(test.after, result) { + t.Errorf("%s: value does not equal expected: exp: \"%v\""+ + " got: \"%v\"", test.name, test.after, result) + } +} +func TestRemoveOpcodeByDatas(t *testing.T) { + for i := range removeOpcodeByDataTests { + testRemoveOpcodeByData(t, &removeOpcodeByDataTests[i]) + } +} + +// Tests for the script type logic + +type scriptTypeTest struct { + name string + script []byte + scripttype btcscript.TstScriptType +} + +var scriptTypeTests = []scriptTypeTest{ + // tx 0437cd7f8525ceed2324359c2d0ba26006d92d85. + scriptTypeTest{ + name: "Pay Pubkey", + script: []byte{ + btcscript.OP_DATA_65, + 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, + 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 0xb6, + 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 0xd7, + 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0, 0xea, + 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64, 0xf8, + 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, + 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, + 0x12, 0xa3, + btcscript.OP_CHECKSIG, + }, + scripttype: btcscript.TstPubKeyTy, + }, + // tx 599e47a8114fe098103663029548811d2651991b62397e057f0c863c2bc9f9ea + scriptTypeTest{ + name: "Pay PubkeyHash", + script: []byte{ + btcscript.OP_DUP, + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0x66, 0x0d, 0x4e, 0xf3, 0xa7, 0x43, 0xe3, 0xe6, 0x96, + 0xad, 0x99, 0x03, 0x64, 0xe5, 0x55, 0xc2, 0x71, 0xad, + 0x50, 0x4b, + btcscript.OP_EQUALVERIFY, + btcscript.OP_CHECKSIG, + }, + scripttype: btcscript.TstPubKeyHashTy, + }, + // part of tx 6d36bc17e947ce00bb6f12f8e7a56a1585c5a36188ffa2b05e10b4743273a74b + // codeseparator parts have been elided. (bitcoind's checks for multisig + // type doesn't have codesep etc either. + scriptTypeTest{ + name: "multisig", + script: []byte{ + btcscript.OP_TRUE, + btcscript.OP_DATA_33, + 0x02, 0x32, 0xab, 0xdc, 0x89, 0x3e, 0x7f, 0x06, 0x31, + 0x36, 0x4d, 0x7f, 0xd0, 0x1c, 0xb3, 0x3d, 0x24, 0xda, + 0x45, 0x32, 0x9a, 0x00, 0x35, 0x7b, 0x3a, 0x78, 0x86, + 0x21, 0x1a, 0xb4, 0x14, 0xd5, 0x5a, + btcscript.OP_TRUE, + btcscript.OP_CHECK_MULTISIG, + }, + scripttype: btcscript.TstMultiSigTy, + }, + // tx e5779b9e78f9650debc2893fd9636d827b26b4ddfa6a8172fe8708c924f5c39d + // P2SH + scriptTypeTest{ + name: "P2SH", + script: []byte{ + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0x43, 0x3e, 0xc2, 0xac, 0x1f, 0xfa, 0x1b, 0x7b, 0x7d, + 0x02, 0x7f, 0x56, 0x45, 0x29, 0xc5, 0x71, 0x97, 0xf9, + 0xae, 0x88, + btcscript.OP_EQUAL, + }, + scripttype: btcscript.TstScriptHashTy, + }, +} + +func testScriptType(t *testing.T, test *scriptTypeTest) { + scripttype := btcscript.TstTypeOfScript(test.script) + if scripttype != test.scripttype { + t.Errorf("%s: expected %s got %s", test.name, test.scripttype, + scripttype) + } +} + +func TestScriptTypes(t *testing.T) { + for i := range scriptTypeTests { + testScriptType(t, &scriptTypeTests[i]) + } +} diff --git a/stack.go b/stack.go new file mode 100644 index 00000000..a1efa8f9 --- /dev/null +++ b/stack.go @@ -0,0 +1,350 @@ +// Copyright (c) 2013 Conformal Systems LLC. +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcscript + +import ( + "math/big" +) + +// asInt converts a byte array to a bignum by treating it as a little endian +// number with sign bit. +func asInt(v []byte) *big.Int { + if len(v) == 0 { + return big.NewInt(0) + } + negative := false + msb := v[len(v)-1] + if msb&0x80 == 0x80 { + negative = true + // remove sign bit + v[len(v)-1] &= 0x7f + } + // trim leading 0 bytes + for ; msb == 0; msb = v[len(v)-1] { + v = v[:len(v)-1] + if len(v) == 0 { + break + } + } + // reverse bytes with a copy since stack is immutable. + intArray := make([]byte, len(v)) + for i := range v { + intArray[len(v)-i-1] = v[i] + } + + num := new(big.Int).SetBytes(intArray) + if negative { + num = num.Neg(num) + } + return num +} + +// fromInt provies a Big.Int in little endian format with the high bit of the +// msb donating sign. +func fromInt(v *big.Int) []byte { + negative := false + if v.Sign() == -1 { + negative = true + } + // Int.Bytes() trims leading zeros for us, so we don't have to. + b := v.Bytes() + if len(b) == 0 { + // negative 0 + if negative { + return []byte{0x80} + } + // normal 0 + return []byte{} + } + arr := make([]byte, len(b)) + for i := range b { + arr[len(b)-i-1] = b[i] + } + // if would otherwise be negative, add a zero byte + if arr[len(arr)-1]&0x80 == 0x80 { + arr = append(arr, 0) + } + if negative { + arr[len(arr)-1] |= 0x80 + } + return arr +} + +// asBool gets the boolean value of the byte array. +func asBool(t []byte) bool { + for i := range t { + if t[i] != 0 { + return true + } + } + return false +} + +// fromBool converts a boolean into the appropriate byte array. +func fromBool(v bool) []byte { + if v { + return []byte{1} + } + return []byte{0} +} + +// Stack represents a stack of immutable objects to be used with bitcoin scripts +// Objects may be shared, therefore in usage if a value is to be changed it +// *must* be deep-copied first to avoid changing other values on the stack. +type Stack struct { + stk [][]byte +} + +// PushByteArray adds the given back array to the top of the stack. +func (s *Stack) PushByteArray(so []byte) { + s.stk = append(s.stk, so) +} + +// PushInt converts the provided bignum to a suitable byte array then pushes +// it onto the top of the stack. +func (s *Stack) PushInt(val *big.Int) { + s.PushByteArray(fromInt(val)) +} + +// PushBool converts the provided boolean to a suitable byte array then pushes +// it onto the top of the stack. +func (s *Stack) PushBool(val bool) { + s.PushByteArray(fromBool(val)) +} + +// PopByteArray pops the value off the top of the stack and returns it. +func (s *Stack) PopByteArray() ([]byte, error) { + return s.nipN(0) +} + +// PopInt pops the value off the top of the stack, converts it into a bignum and +// returns it. +func (s *Stack) PopInt() (*big.Int, error) { + so, err := s.PopByteArray() + if err != nil { + return nil, err + } + return asInt(so), nil +} + +// PopBool pops the value off the top of the stack, converts it into a bool and +// returns it. +func (s *Stack) PopBool() (bool, error) { + so, err := s.PopByteArray() + if err != nil { + return false, err + } + return asBool(so), nil +} + +// PeekByteArray returns the nth item on the stack without removing it. +func (s *Stack) PeekByteArray(idx int) (so []byte, err error) { + sz := len(s.stk) + if idx < 0 || idx >= sz { + return nil, StackErrUnderflow + } + return s.stk[sz-idx-1], nil +} + +// PeekInt returns the nth item on the stack as a bignum without removing it. +func (s *Stack) PeekInt(idx int) (i *big.Int, err error) { + so, err := s.PeekByteArray(idx) + if err != nil { + return nil, err + } + return asInt(so), nil +} + +// PeekBool returns the nth item on the stack as a bool without removing it. +func (s *Stack) PeekBool(idx int) (i bool, err error) { + so, err := s.PeekByteArray(idx) + if err != nil { + return false, err + } + return asBool(so), nil +} + +// nipN is an internal function that removes the nth item on the stack and +// returns it. +func (s *Stack) nipN(idx int) (so []byte, err error) { + sz := len(s.stk) + if idx < 0 || idx > sz-1 { + err = StackErrUnderflow + return + } + so = s.stk[sz-idx-1] + if idx == 0 { + s.stk = s.stk[:sz-1] + } else if idx == sz-1 { + s.stk = s.stk[1:] + } else { + s1 := s.stk[sz-idx : sz] + s.stk = s.stk[:sz-idx-1] + s.stk = append(s.stk, s1...) + } + return +} + +// NipN removes the Nth object on the stack +func (s *Stack) NipN(idx int) error { + _, err := s.nipN(idx) + return err +} + +// Tuck copies the item at the top of the stack and inserts it before the 2nd +// to top item. e.g.: 2,1 -> 2,1,2 +func (s *Stack) Tuck() error { + so2, err := s.PopByteArray() + if err != nil { + return err + } + so1, err := s.PopByteArray() + if err != nil { + return err + } + s.PushByteArray(so2) // stack 2 + s.PushByteArray(so1) // stack 1,2 + s.PushByteArray(so2) // stack 2,1,2 + + return nil +} + +// Depth returns the number of items on the stack. +func (s *Stack) Depth() (sz int) { + sz = len(s.stk) + return +} + +// DropN removes the top N items from the stack. +// e.g. +// DropN(1): 1,2,3 -> 1,2 +// DropN(2): 1,2,3 -> 1 +func (s *Stack) DropN(n int) error { + if n < 1 { + return StackErrInvalidArgs + } + for ; n > 0; n-- { + _, err := s.PopByteArray() + if err != nil { + return err + } + } + return nil +} + +// DupN duplicates the top N items on the stack. +// e.g. +// DupN(1): 1,2,3 -> 1,2,3,3 +// DupN(2): 1,2,3 -> 1,2,3,2,3 +func (s *Stack) DupN(n int) error { + if n < 1 { + return StackErrInvalidArgs + } + // Iteratively duplicate the value n-1 down the stack n times. + // this leaves us with an in-order duplicate of the top N items on the + // stack. + for i := n; i > 0; i-- { + so, err := s.PeekByteArray(n - 1) + if err != nil { + return err + } + s.PushByteArray(so) + } + return nil +} + +// RotN rotates the top 3N items on the stack to the left +// e.g. +// RotN(1): 1,2,3 -> 2,3,1 +func (s *Stack) RotN(n int) error { + if n < 1 { + return StackErrInvalidArgs + } + entry := 3*n - 1 + // Nip the 3n-1th item from the stack to the top n times to rotate + // them up to the head of the stack. + for i := n; i > 0; i-- { + so, err := s.nipN(entry) + if err != nil { + return err + } + + s.PushByteArray(so) + } + return nil +} + +// SwapN swaps the top N items on the stack with those below them. +// E.g.: +// SwapN(1): 1,2 -> 2,1 +// SwapN(2): 1,2,3,4 -> 3,4,1,2 +func (s *Stack) SwapN(n int) error { + if n < 1 { + return StackErrInvalidArgs + } + entry := 2*n - 1 + for i := n; i > 0; i-- { + // swap 2n-1th entry to topj + so, err := s.nipN(entry) + if err != nil { + return err + } + + s.PushByteArray(so) + } + return nil +} + +// OverN copies N items N spaces back to the top of the stack. +// e.g.: +// OverN(1): 1,2 -> 1,2,1 +// OverN(2): 1,2,3,4 -> 1,2,3,4,1,2 +func (s *Stack) OverN(n int) error { + if n < 1 { + return StackErrInvalidArgs + } + // Copy 2n-1th entry to top of the stack + entry := 2*n - 1 + for ; n > 0; n-- { + so, err := s.PeekByteArray(entry) + if err != nil { + return err + } + s.PushByteArray(so) + // 4,1,2,3,4, now code original 3rd entry to top. + } + + return nil +} + +// PickN copies the item N items back in the stack to the top. +// e.g.: +// PickN(1): 1,2,3 -> 1,2,3,2 +// PickN(2): 1,2,3 -> 1,2,3,1 +func (s *Stack) PickN(n int) error { + so, err := s.PeekByteArray(n) + if err != nil { + return err + } + + s.PushByteArray(so) + + return nil +} + +// RollN moves the item N items back in the stack to the top. +// e.g.: +// RollN(1): 1,2,3 -> 1,3,2 +// RollN(2): 1,2,3 -> 2,3,1 +func (s *Stack) RollN(n int) error { + so, err := s.nipN(n) + if err != nil { + return err + } + + s.PushByteArray(so) + + return nil +} diff --git a/stack_test.go b/stack_test.go new file mode 100644 index 00000000..cfdf97a3 --- /dev/null +++ b/stack_test.go @@ -0,0 +1,818 @@ +// Copyright (c) 2013 Conformal Systems LLC. +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcscript_test + +import ( + "bytes" + "errors" + "github.com/conformal/btcscript" + "math/big" + "testing" +) + +type stackTest struct { + name string + before [][]byte + operation func(*btcscript.Stack) error + expectedReturn error + after [][]byte +} + +var stackTests = []stackTest{ + { + "noop", + [][]byte{{1}, {2}, {3}, {4}, {5}}, + func(stack *btcscript.Stack) error { + return nil + }, + nil, + [][]byte{{1}, {2}, {3}, {4}, {5}}, + }, + { + "peek underflow (byte)", + [][]byte{{1}, {2}, {3}, {4}, {5}}, + func(stack *btcscript.Stack) error { + _, err := stack.PeekByteArray(5) + return err + }, + btcscript.StackErrUnderflow, + [][]byte{}, + }, + { + "peek underflow (int)", + [][]byte{{1}, {2}, {3}, {4}, {5}}, + func(stack *btcscript.Stack) error { + _, err := stack.PeekInt(5) + return err + }, + btcscript.StackErrUnderflow, + [][]byte{}, + }, + { + "peek underflow (bool)", + [][]byte{{1}, {2}, {3}, {4}, {5}}, + func(stack *btcscript.Stack) error { + _, err := stack.PeekBool(5) + return err + }, + btcscript.StackErrUnderflow, + [][]byte{}, + }, + { + "pop", + [][]byte{{1}, {2}, {3}, {4}, {5}}, + func(stack *btcscript.Stack) error { + val, err := stack.PopByteArray() + if err != nil { + return err + } + if !bytes.Equal(val, []byte{5}) { + return errors.New("not equal!") + } + return err + }, + nil, + [][]byte{{1}, {2}, {3}, {4}}, + }, + { + "pop", + [][]byte{{1}, {2}, {3}, {4}, {5}}, + func(stack *btcscript.Stack) error { + val, err := stack.PopByteArray() + if err != nil { + return err + } + if !bytes.Equal(val, []byte{5}) { + return errors.New("not equal!") + } + return err + }, + nil, + [][]byte{{1}, {2}, {3}, {4}}, + }, + { + "pop everything", + [][]byte{{1}, {2}, {3}, {4}, {5}}, + func(stack *btcscript.Stack) error { + for i := 0; i < 5; i++ { + _, err := stack.PopByteArray() + if err != nil { + return err + } + } + return nil + }, + nil, + [][]byte{}, + }, + { + "pop underflow", + [][]byte{{1}, {2}, {3}, {4}, {5}}, + func(stack *btcscript.Stack) error { + for i := 0; i < 6; i++ { + _, err := stack.PopByteArray() + if err != nil { + return err + } + } + return nil + }, + btcscript.StackErrUnderflow, + [][]byte{}, + }, + { + "pop bool", + [][]byte{{0}}, + func(stack *btcscript.Stack) error { + val, err := stack.PopBool() + if err != nil { + return err + } + + if val != false { + return errors.New("unexpected value") + } + return nil + }, + nil, + [][]byte{}, + }, + { + "pop bool", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + val, err := stack.PopBool() + if err != nil { + return err + } + + if val != true { + return errors.New("unexpected value") + } + return nil + }, + nil, + [][]byte{}, + }, + { + "pop bool", + [][]byte{}, + func(stack *btcscript.Stack) error { + _, err := stack.PopBool() + if err != nil { + return err + } + + return nil + }, + btcscript.StackErrUnderflow, + [][]byte{}, + }, + // XXX test popInt -> byte format matters here. + { + "dup", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + err := stack.DupN(1) + if err != nil { + return err + } + + return nil + }, + nil, + [][]byte{{1}, {1}}, + }, + { + "dup2", + [][]byte{{1}, {2}}, + func(stack *btcscript.Stack) error { + err := stack.DupN(2) + if err != nil { + return err + } + + return nil + }, + nil, + [][]byte{{1}, {2}, {1}, {2}}, + }, + { + "dup3", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + err := stack.DupN(3) + if err != nil { + return err + } + + return nil + }, + nil, + [][]byte{{1}, {2}, {3}, {1}, {2}, {3}}, + }, + { + "dup0", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + err := stack.DupN(0) + if err != nil { + return err + } + + return nil + }, + btcscript.StackErrInvalidArgs, + [][]byte{}, + }, + { + "dup-1", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + err := stack.DupN(-1) + if err != nil { + return err + } + + return nil + }, + btcscript.StackErrInvalidArgs, + [][]byte{}, + }, + { + "dup too much", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + err := stack.DupN(2) + if err != nil { + return err + } + + return nil + }, + btcscript.StackErrUnderflow, + [][]byte{}, + }, + { + "dup-1", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + err := stack.DupN(-1) + if err != nil { + return err + } + + return nil + }, + btcscript.StackErrInvalidArgs, + [][]byte{}, + }, + { + "PushBool true", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushBool(true) + + return nil + }, + nil, + [][]byte{{1}}, + }, + { + "PushBool false", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushBool(false) + + return nil + }, + nil, + [][]byte{{0}}, + }, + { + "PushBool PopBool", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushBool(true) + val, err := stack.PopBool() + if err != nil { + return err + } + if val != true { + return errors.New("unexpected value") + } + + return nil + }, + nil, + [][]byte{}, + }, + { + "PushBool PopBool 2", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushBool(false) + val, err := stack.PopBool() + if err != nil { + return err + } + if val != false { + return errors.New("unexpected value") + } + + return nil + }, + nil, + [][]byte{}, + }, + { + "PushInt PopBool", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushInt(big.NewInt(1)) + val, err := stack.PopBool() + if err != nil { + return err + } + if val != true { + return errors.New("unexpected value") + } + + return nil + }, + nil, + [][]byte{}, + }, + { + "PushInt PopBool 2", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushInt(big.NewInt(0)) + val, err := stack.PopBool() + if err != nil { + return err + } + if val != false { + return errors.New("unexpected value") + } + + return nil + }, + nil, + [][]byte{}, + }, + { + "PushInt PopBool 2", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushInt(big.NewInt(0)) + val, err := stack.PopBool() + if err != nil { + return err + } + if val != false { + return errors.New("unexpected value") + } + + return nil + }, + nil, + [][]byte{}, + }, + { + "Nip top", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + return stack.NipN(0) + }, + nil, + [][]byte{{1}, {2}}, + }, + { + "Nip middle", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + return stack.NipN(1) + }, + nil, + [][]byte{{1}, {3}}, + }, + { + "Nip low", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + return stack.NipN(2) + }, + nil, + [][]byte{{2}, {3}}, + }, + { + "Nip too much", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + // bite off more than we can chew + return stack.NipN(3) + }, + btcscript.StackErrUnderflow, + [][]byte{{2}, {3}}, + }, + { + "Nip too much", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + // bite off more than we can chew + return stack.NipN(3) + }, + btcscript.StackErrUnderflow, + [][]byte{{2}, {3}}, + }, + { + "keep on tucking", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + return stack.Tuck() + }, + nil, + [][]byte{{1}, {3}, {2}, {3}}, + }, + { + "a little tucked up", + [][]byte{{1}}, // too few arguments for tuck + func(stack *btcscript.Stack) error { + return stack.Tuck() + }, + btcscript.StackErrUnderflow, + [][]byte{}, + }, + { + "all tucked up", + [][]byte{}, // too few arguments for tuck + func(stack *btcscript.Stack) error { + return stack.Tuck() + }, + btcscript.StackErrUnderflow, + [][]byte{}, + }, + { + "drop 1", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.DropN(1) + }, + nil, + [][]byte{{1}, {2}, {3}}, + }, + { + "drop 2", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.DropN(2) + }, + nil, + [][]byte{{1}, {2}}, + }, + { + "drop 3", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.DropN(3) + }, + nil, + [][]byte{{1}}, + }, + { + "drop 4", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.DropN(4) + }, + nil, + [][]byte{}, + }, + { + "drop 4/5", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.DropN(5) + }, + btcscript.StackErrUnderflow, + [][]byte{}, + }, + { + "drop invalid", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.DropN(0) + }, + btcscript.StackErrInvalidArgs, + [][]byte{}, + }, + { + "Rot1", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.RotN(1) + }, + nil, + [][]byte{{1}, {3}, {4}, {2}}, + }, + { + "Rot2", + [][]byte{{1}, {2}, {3}, {4}, {5}, {6}}, + func(stack *btcscript.Stack) error { + return stack.RotN(2) + }, + nil, + [][]byte{{3}, {4}, {5}, {6}, {1}, {2}}, + }, + { + "Rot too little", + [][]byte{{1}, {2}}, + func(stack *btcscript.Stack) error { + return stack.RotN(1) + }, + btcscript.StackErrUnderflow, + [][]byte{}, + }, + { + "Rot0", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + return stack.RotN(0) + }, + btcscript.StackErrInvalidArgs, + [][]byte{}, + }, + { + "Swap1", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.SwapN(1) + }, + nil, + [][]byte{{1}, {2}, {4}, {3}}, + }, + { + "Swap2", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.SwapN(2) + }, + nil, + [][]byte{{3}, {4}, {1}, {2}}, + }, + { + "Swap too little", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + return stack.SwapN(1) + }, + btcscript.StackErrUnderflow, + [][]byte{}, + }, + { + "Swap0", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + return stack.SwapN(0) + }, + btcscript.StackErrInvalidArgs, + [][]byte{}, + }, + { + "Over1", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.OverN(1) + }, + nil, + [][]byte{{1}, {2}, {3}, {4}, {3}}, + }, + { + "Over2", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.OverN(2) + }, + nil, + [][]byte{{1}, {2}, {3}, {4}, {1}, {2}}, + }, + { + "Over too little", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + return stack.OverN(1) + }, + btcscript.StackErrUnderflow, + [][]byte{}, + }, + { + "Over0", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + return stack.OverN(0) + }, + btcscript.StackErrInvalidArgs, + [][]byte{}, + }, + { + "Pick1", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.PickN(1) + }, + nil, + [][]byte{{1}, {2}, {3}, {4}, {3}}, + }, + { + "Pick2", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.PickN(2) + }, + nil, + [][]byte{{1}, {2}, {3}, {4}, {2}}, + }, + { + "Pick too little", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + return stack.PickN(1) + }, + btcscript.StackErrUnderflow, + [][]byte{}, + }, + { + "Roll1", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.RollN(1) + }, + nil, + [][]byte{{1}, {2}, {4}, {3}}, + }, + { + "Roll2", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.RollN(2) + }, + nil, + [][]byte{{1}, {3}, {4}, {2}}, + }, + { + "Roll too little", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + return stack.RollN(1) + }, + btcscript.StackErrUnderflow, + [][]byte{}, + }, + { + "Peek bool", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + // Peek bool is otherwise pretty well tested, just check + // it works. + val, err := stack.PeekBool(0) + if err != nil { + return err + } + if val != true { + return errors.New("invalid result") + } + return nil + }, + nil, + [][]byte{{1}}, + }, + { + "Peek bool 2", + [][]byte{{0}}, + func(stack *btcscript.Stack) error { + // Peek bool is otherwise pretty well tested, just check + // it works. + val, err := stack.PeekBool(0) + if err != nil { + return err + } + if val != false { + return errors.New("invalid result") + } + return nil + }, + nil, + [][]byte{{0}}, + }, + { + "Peek int", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + // Peek int is otherwise pretty well tested, just check + // it works. + val, err := stack.PeekInt(0) + if err != nil { + return err + } + if val.Cmp(big.NewInt(1)) != 0 { + return errors.New("invalid result") + } + return nil + }, + nil, + [][]byte{{1}}, + }, + { + "Peek int 2", + [][]byte{{0}}, + func(stack *btcscript.Stack) error { + // Peek int is otherwise pretty well tested, just check + // it works. + val, err := stack.PeekInt(0) + if err != nil { + return err + } + if val.Cmp(big.NewInt(0)) != 0 { + return errors.New("invalid result") + } + return nil + }, + nil, + [][]byte{{0}}, + }, + { + "pop int", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushInt(big.NewInt(1)) + // Peek int is otherwise pretty well tested, just check + // it works. + val, err := stack.PopInt() + if err != nil { + return err + } + if val.Cmp(big.NewInt(1)) != 0 { + return errors.New("invalid result") + } + return nil + }, + nil, + [][]byte{}, + }, + { + "pop empty", + [][]byte{}, + func(stack *btcscript.Stack) error { + // Peek int is otherwise pretty well tested, just check + // it works. + _, err := stack.PopInt() + return err + }, + btcscript.StackErrUnderflow, + [][]byte{}, + }, +} + +func doTest(t *testing.T, test stackTest) { + stack := btcscript.Stack{} + + for i := range test.before { + stack.PushByteArray(test.before[i]) + } + err := test.operation(&stack) + if err != test.expectedReturn { + t.Errorf("%s: operation return not what expected: %v vs %v", + test.name, err, test.expectedReturn) + } + if err != nil { + return + } + if len(test.after) != stack.Depth() { + t.Errorf("%s: stack depth doesn't match expected: %v vs %v", + test.name, len(test.after), stack.Depth()) + } + for i := range test.after { + val, err := stack.PeekByteArray(stack.Depth() - i - 1) + if err != nil { + t.Errorf("%s: can't peek %dth stack entry: %v", + test.name, i, err) + break + } + + if !bytes.Equal(val, test.after[i]) { + t.Errorf("%s: %dth stack entry doesn't match "+ + "expected: %v vs %v", test.name, i, val, + test.after[i]) + break + } + } +} + +func TestStack(t *testing.T) { + for i := range stackTests { + doTest(t, stackTests[i]) + } +} diff --git a/test_coverage.txt b/test_coverage.txt new file mode 100644 index 00000000..8aaf961e --- /dev/null +++ b/test_coverage.txt @@ -0,0 +1,138 @@ + +github.com/conformal/btcscript/stack.go asInt 100.00% (18/18) +github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) +github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) +github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12) +github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12) +github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) +github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) +github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) +github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) +github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) +github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) +github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) +github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) +github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) +github.com/conformal/btcscript/script.go unparseScript 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) +github.com/conformal/btcscript/script.go getStack 100.00% (4/4) +github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) +github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) +github.com/conformal/btcscript/script.go setStack 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) +github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go init 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) +github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) +github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) +github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) +github.com/conformal/btcscript/log.go init 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 96.43% (54/56) +github.com/conformal/btcscript/script.go NewScript 95.24% (20/21) +github.com/conformal/btcscript/address.go ScriptToAddress 94.92% (56/59) +github.com/conformal/btcscript/script.go parseScript 93.75% (30/32) +github.com/conformal/btcscript/stack.go fromInt 87.50% (14/16) +github.com/conformal/btcscript/script.go Script.Step 86.11% (31/36) +github.com/conformal/btcscript/script.go typeOfScript 83.33% (5/6) +github.com/conformal/btcscript/opcode.go opcodeCheckSig 80.77% (21/26) +github.com/conformal/btcscript/opcode.go parsedOpcode.exec 80.00% (4/5) +github.com/conformal/btcscript/script.go Script.DisasmScript 80.00% (4/5) +github.com/conformal/btcscript/script.go Script.DisasmPC 75.00% (3/4) +github.com/conformal/btcscript/script.go Script.curPC 75.00% (3/4) +github.com/conformal/btcscript/script.go isPushOnly 75.00% (3/4) +github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) +github.com/conformal/btcscript/script.go Script.calcScriptHash 71.43% (25/35) +github.com/conformal/btcscript/script.go isMultiSig 61.54% (8/13) +github.com/conformal/btcscript/opcode.go opcodeSha1 60.00% (3/5) +github.com/conformal/btcscript/script.go Script.validPC 60.00% (3/5) +github.com/conformal/btcscript/script.go Script.Execute 55.17% (16/29) +github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) +github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) +github.com/conformal/btcscript ------------------------- 92.51% (828/895) + From 2a8cf9f44f2a501fcd6df72662fdaa529813a073 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 13 Jun 2013 15:18:58 -0500 Subject: [PATCH 003/174] Use correct import path for btcec. --- opcode.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opcode.go b/opcode.go index 504d8ff3..613b8361 100644 --- a/opcode.go +++ b/opcode.go @@ -11,11 +11,11 @@ import ( "crypto/sha1" "crypto/sha256" "fmt" + "github.com/conformal/btcec" "github.com/conformal/btcwire" "github.com/davecgh/go-spew/spew" "hash" "math/big" - "opensource.conformal.com/go/btcd/btcec" ) // An opcode defines the information related to a btcscript opcode. From bc41004b03fd08a3c1ad1d0833ba503668c94c23 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Tue, 18 Jun 2013 17:37:07 +0100 Subject: [PATCH 004/174] Use errors.New() not fmt.Errorf() when no fmt string. --- script.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/script.go b/script.go index 63629afe..b1bef325 100644 --- a/script.go +++ b/script.go @@ -71,11 +71,11 @@ var StackErrElementTooBig = errors.New("Element in script too large") // StackErrUnknownAddress is returned when ScriptToAddress does not recognise // the pattern of the script and thus can not find the address for payment. -var StackErrUnknownAddress = fmt.Errorf("non-recognised address") +var StackErrUnknownAddress = errors.New("non-recognised address") // StackErrScriptFailed is returned when at the end of a script the boolean // on top of the stack is false signifying that the script has failed. -var StackErrScriptFailed = fmt.Errorf("execute fail, fail on stack") +var StackErrScriptFailed = errors.New("execute fail, fail on stack") // Bip16Activation is the timestamp where BIP0016 is valid to use in the // blockchain. To be used to determine if BIP0016 should be called for or not. From 7b08a4e127a7c361287e6e55c6aad433cf2568ed Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Tue, 18 Jun 2013 17:38:18 +0100 Subject: [PATCH 005/174] Number of operations is per-script not per-transaction. Reset the counter at the end of each script. --- script.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script.go b/script.go index b1bef325..c10fdfb1 100644 --- a/script.go +++ b/script.go @@ -413,7 +413,7 @@ func (m *Script) Step() (done bool, err error) { // prepare for next instruction m.scriptoff++ if m.scriptoff >= len(m.scripts[m.scriptidx]) { - // should only be == from checks before + m.numOps = 0 // number of ops is per script. m.scriptoff = 0 if m.scriptidx == 0 && m.bip16 { m.savedFirstStack = m.GetStack() From df0c0b27d19ee54019593f227b5e888652242cc9 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Tue, 18 Jun 2013 17:39:00 +0100 Subject: [PATCH 006/174] Factor the end-of-script error handling into a function. Use it to reduce code dpulication in the bip16 case. In addition we export it so that that a user could run: for !done && err == nil { done, err = s.Step() } err = s.CheckErrorCondition() manually instead of having to run Execute(). --- script.go | 45 ++++++++++---- test_coverage.txt | 147 +++++++++++++++++++++++----------------------- 2 files changed, 108 insertions(+), 84 deletions(-) diff --git a/script.go b/script.go index c10fdfb1..9d68e4d6 100644 --- a/script.go +++ b/script.go @@ -77,6 +77,15 @@ var StackErrUnknownAddress = errors.New("non-recognised address") // on top of the stack is false signifying that the script has failed. var StackErrScriptFailed = errors.New("execute fail, fail on stack") +// StackErrScriptUnfinished is returned when CheckErrorCondition is called +// on a script that has not finished executing. +var StackErrScriptUnfinished = errors.New("Error check when script unfinished") + +// StackErrEmpyStack is returned when the stack is empty at the end of +// execution. Normal operation requires that a boolean is on top of the stack +// when the scripts have finished executing. +var StackErrEmptyStack = errors.New("Stack empty at end of execution") + // Bip16Activation is the timestamp where BIP0016 is valid to use in the // blockchain. To be used to determine if BIP0016 should be called for or not. // This timestamp corresponds to Sun Apr 1 00:00:00 UTC 2012. @@ -358,8 +367,21 @@ func (s *Script) Execute() (err error) { return dstr + astr })) } + + return s.CheckErrorCondition() +} + +// CheckErrorCondition returns nil if the running script has ended and was +// successful, leaving a a true boolean on the stack. An error otherwise, +// including if the script has not finished. +func (s *Script) CheckErrorCondition() (err error) { + // Check we are actually done. if pc is past the end of script array + // then we have run out of scripts to run. + if s.scriptidx < len(s.scripts) { + return StackErrScriptUnfinished + } if s.dstack.Depth() < 1 { - return fmt.Errorf("stack empty at end of execution") + return StackErrEmptyStack } v, err := s.dstack.PopBool() if err == nil && v == false { @@ -367,8 +389,8 @@ func (s *Script) Execute() (err error) { log.Tracef("%v", func() string { dis0, _ := s.DisasmScript(0) dis1, _ := s.DisasmScript(1) - return fmt.Sprintf("script0: %s\n script1: %s", - dis0, dis1) + return fmt.Sprintf("scripts failed: script0: %s\n"+ + "script1: %s", dis0, dis1) }) err = StackErrScriptFailed } @@ -376,7 +398,6 @@ func (s *Script) Execute() (err error) { // conditional execution stack context left active err = StackErrMissingEndif } - return err } @@ -416,17 +437,18 @@ func (m *Script) Step() (done bool, err error) { m.numOps = 0 // number of ops is per script. m.scriptoff = 0 if m.scriptidx == 0 && m.bip16 { + m.scriptidx++ m.savedFirstStack = m.GetStack() } else if m.scriptidx == 1 && m.bip16 { - // Check for successful completion of script - v, err := m.dstack.PopBool() + // Put us past the end for CheckErrorCondition() + m.scriptidx++ + // We check script ran ok, if so then we pull + // the script out of the first stack and executre that. + err := m.CheckErrorCondition() if err != nil { return false, err } - if v == false { - return false, StackErrScriptFailed - } - // check that first element on stack is a bool + script := m.savedFirstStack[len(m.savedFirstStack)-1] pops, err := parseScript(script) if err != nil { @@ -436,8 +458,9 @@ func (m *Script) Step() (done bool, err error) { // Set stack to be the stack from first script // minus the script itself m.SetStack(m.savedFirstStack[:len(m.savedFirstStack)-1]) + } else { + m.scriptidx++ } - m.scriptidx++ // there are zero length scripts in the wild if m.scriptidx < len(m.scripts) && m.scriptoff >= len(m.scripts[m.scriptidx]) { m.scriptidx++ diff --git a/test_coverage.txt b/test_coverage.txt index 8aaf961e..228313be 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -2,137 +2,138 @@ github.com/conformal/btcscript/stack.go asInt 100.00% (18/18) github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) -github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12) github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12) -github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) +github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) -github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) -github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) -github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) +github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) -github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) +github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) +github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) -github.com/conformal/btcscript/script.go unparseScript 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) +github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) +github.com/conformal/btcscript/script.go unparseScript 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) -github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) +github.com/conformal/btcscript/script.go setStack 100.00% (3/3) +github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) -github.com/conformal/btcscript/script.go setStack 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) -github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) +github.com/conformal/btcscript/opcode.go init 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) +github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go init 100.00% (1/1) +github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) +github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) -github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) -github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) github.com/conformal/btcscript/log.go init 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 96.43% (54/56) github.com/conformal/btcscript/script.go NewScript 95.24% (20/21) github.com/conformal/btcscript/address.go ScriptToAddress 94.92% (56/59) github.com/conformal/btcscript/script.go parseScript 93.75% (30/32) +github.com/conformal/btcscript/script.go Script.Step 89.19% (33/37) github.com/conformal/btcscript/stack.go fromInt 87.50% (14/16) -github.com/conformal/btcscript/script.go Script.Step 86.11% (31/36) github.com/conformal/btcscript/script.go typeOfScript 83.33% (5/6) github.com/conformal/btcscript/opcode.go opcodeCheckSig 80.77% (21/26) github.com/conformal/btcscript/opcode.go parsedOpcode.exec 80.00% (4/5) github.com/conformal/btcscript/script.go Script.DisasmScript 80.00% (4/5) -github.com/conformal/btcscript/script.go Script.DisasmPC 75.00% (3/4) -github.com/conformal/btcscript/script.go Script.curPC 75.00% (3/4) -github.com/conformal/btcscript/script.go isPushOnly 75.00% (3/4) github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) +github.com/conformal/btcscript/script.go Script.curPC 75.00% (3/4) +github.com/conformal/btcscript/script.go Script.DisasmPC 75.00% (3/4) +github.com/conformal/btcscript/script.go isPushOnly 75.00% (3/4) github.com/conformal/btcscript/script.go Script.calcScriptHash 71.43% (25/35) +github.com/conformal/btcscript/script.go Script.CheckErrorCondition 71.43% (10/14) github.com/conformal/btcscript/script.go isMultiSig 61.54% (8/13) github.com/conformal/btcscript/opcode.go opcodeSha1 60.00% (3/5) github.com/conformal/btcscript/script.go Script.validPC 60.00% (3/5) -github.com/conformal/btcscript/script.go Script.Execute 55.17% (16/29) +github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript ------------------------- 92.51% (828/895) +github.com/conformal/btcscript -------------------------- 92.55% (832/899) From 4692d64f68fb145a2f4f97cf51bd32593b9ec87d Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Tue, 18 Jun 2013 23:36:44 +0100 Subject: [PATCH 007/174] permit tests expect fail for nonspecified return code. Use this to test the pubkey paths in checksig which return btcec errors which we don't define. all of the other active tests know the return code we need. --- script_test.go | 220 ++++++++++++++++++++++++++++++++++++++++++++-- test_coverage.txt | 4 +- 2 files changed, 215 insertions(+), 9 deletions(-) diff --git a/script_test.go b/script_test.go index 463344d8..9f65969a 100644 --- a/script_test.go +++ b/script_test.go @@ -12,12 +12,13 @@ import ( ) type txTest struct { - name string - tx *btcwire.MsgTx - pkScript []byte // output script of previous tx - idx int - bip16 bool - err error + name string + tx *btcwire.MsgTx + pkScript []byte // output script of previous tx + idx int + bip16 bool + err error + shouldFail bool } var txTests = []txTest{ @@ -221,6 +222,207 @@ var txTests = []txTest{ idx: 0, err: btcscript.StackErrScriptFailed, }, + txTest{ + name: "CheckSig invalid signature", + tx: &btcwire.MsgTx{ + Version: 1, + TxIn: []*btcwire.TxIn{ + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash([32]byte{ + 0xc9, 0x97, 0xa5, 0xe5, + 0x6e, 0x10, 0x41, 0x02, + 0xfa, 0x20, 0x9c, 0x6a, + 0x85, 0x2d, 0xd9, 0x06, + 0x60, 0xa2, 0x0b, 0x2d, + 0x9c, 0x35, 0x24, 0x23, + 0xed, 0xce, 0x25, 0x85, + 0x7f, 0xcd, 0x37, 0x04, + }), + Index: 0, + }, + // Signature has length fiddled to + // fail parsing. + SignatureScript: []uint8{ + btcscript.OP_DATA_71, + 0x30, 0x45, 0x02, 0x20, 0x4e, + 0x45, 0xe1, 0x69, 0x32, 0xb8, + 0xaf, 0x51, 0x49, 0x61, 0xa1, + 0xd3, 0xa1, 0xa2, 0x5f, 0xdf, + 0x3f, 0x4f, 0x77, 0x32, 0xe9, + 0xd6, 0x24, 0xc6, 0xc6, 0x15, + 0x48, 0xab, 0x5f, 0xb8, 0xcd, + 0x41, 0x02, 0x20, 0x18, 0x15, + 0x22, 0xec, 0x8e, 0xca, 0x07, + 0xde, 0x48, 0x60, 0xa4, 0xac, + 0xdd, 0x12, 0x90, 0x9d, 0x83, + 0x1c, 0xc5, 0x6c, 0xbb, 0xac, + 0x46, 0x22, 0x08, 0x22, 0x21, + 0xa8, 0x76, 0x8d, 0x1d, 0x09, + 0x01, + }, + + Sequence: 4294967295, + }, + }, + TxOut: []*btcwire.TxOut{ + &btcwire.TxOut{ + Value: 1000000000, + PkScript: []byte{ + btcscript.OP_DATA_65, + 0x04, 0xae, 0x1a, 0x62, 0xfe, + 0x09, 0xc5, 0xf5, 0x1b, 0x13, + 0x90, 0x5f, 0x07, 0xf0, 0x6b, + 0x99, 0xa2, 0xf7, 0x15, 0x9b, + 0x22, 0x25, 0xf3, 0x74, 0xcd, + 0x37, 0x8d, 0x71, 0x30, 0x2f, + 0xa2, 0x84, 0x14, 0xe7, 0xaa, + 0xb3, 0x73, 0x97, 0xf5, 0x54, + 0xa7, 0xdf, 0x5f, 0x14, 0x2c, + 0x21, 0xc1, 0xb7, 0x30, 0x3b, + 0x8a, 0x06, 0x26, 0xf1, 0xba, + 0xde, 0xd5, 0xc7, 0x2a, 0x70, + 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, + btcscript.OP_CHECKSIG, + }, + }, + &btcwire.TxOut{ + Value: 4000000000, + PkScript: []byte{ + btcscript.OP_DATA_65, + 0x04, 0x11, 0xdb, 0x93, 0xe1, + 0xdc, 0xdb, 0x8a, 0x01, 0x6b, + 0x49, 0x84, 0x0f, 0x8c, 0x53, + 0xbc, 0x1e, 0xb6, 0x8a, 0x38, + 0x2e, 0x97, 0xb1, 0x48, 0x2e, + 0xca, 0xd7, 0xb1, 0x48, 0xa6, + 0x90, 0x9a, 0x5c, 0xb2, 0xe0, + 0xea, 0xdd, 0xfb, 0x84, 0xcc, + 0xf9, 0x74, 0x44, 0x64, 0xf8, + 0x2e, 0x16, 0x0b, 0xfa, 0x9b, + 0x8b, 0x64, 0xf9, 0xd4, 0xc0, + 0x3f, 0x99, 0x9b, 0x86, 0x43, + 0xf6, 0x56, 0xb4, 0x12, 0xa3, + btcscript.OP_CHECKSIG, + }, + }, + }, + LockTime: 0, + }, + pkScript: []byte{ + btcscript.OP_DATA_65, + 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, + 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 0xb6, + 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 0xd7, + 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0, 0xea, + 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64, 0xf8, + 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, + 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, + 0x12, 0xa3, btcscript.OP_CHECKSIG, + }, + idx: 0, + shouldFail: true, + }, + txTest{ + name: "CheckSig invalid pubkey", + tx: &btcwire.MsgTx{ + Version: 1, + TxIn: []*btcwire.TxIn{ + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash([32]byte{ + 0xc9, 0x97, 0xa5, 0xe5, + 0x6e, 0x10, 0x41, 0x02, + 0xfa, 0x20, 0x9c, 0x6a, + 0x85, 0x2d, 0xd9, 0x06, + 0x60, 0xa2, 0x0b, 0x2d, + 0x9c, 0x35, 0x24, 0x23, + 0xed, 0xce, 0x25, 0x85, + 0x7f, 0xcd, 0x37, 0x04, + }), + Index: 0, + }, + SignatureScript: []uint8{ + btcscript.OP_DATA_71, + 0x30, 0x44, 0x02, 0x20, 0x4e, + 0x45, 0xe1, 0x69, 0x32, 0xb8, + 0xaf, 0x51, 0x49, 0x61, 0xa1, + 0xd3, 0xa1, 0xa2, 0x5f, 0xdf, + 0x3f, 0x4f, 0x77, 0x32, 0xe9, + 0xd6, 0x24, 0xc6, 0xc6, 0x15, + 0x48, 0xab, 0x5f, 0xb8, 0xcd, + 0x41, 0x02, 0x20, 0x18, 0x15, + 0x22, 0xec, 0x8e, 0xca, 0x07, + 0xde, 0x48, 0x60, 0xa4, 0xac, + 0xdd, 0x12, 0x90, 0x9d, 0x83, + 0x1c, 0xc5, 0x6c, 0xbb, 0xac, + 0x46, 0x22, 0x08, 0x22, 0x21, + 0xa8, 0x76, 0x8d, 0x1d, 0x09, + 0x01, + }, + + Sequence: 4294967295, + }, + }, + TxOut: []*btcwire.TxOut{ + &btcwire.TxOut{ + Value: 1000000000, + PkScript: []byte{ + btcscript.OP_DATA_65, + 0x04, 0xae, 0x1a, 0x62, 0xfe, + 0x09, 0xc5, 0xf5, 0x1b, 0x13, + 0x90, 0x5f, 0x07, 0xf0, 0x6b, + 0x99, 0xa2, 0xf7, 0x15, 0x9b, + 0x22, 0x25, 0xf3, 0x74, 0xcd, + 0x37, 0x8d, 0x71, 0x30, 0x2f, + 0xa2, 0x84, 0x14, 0xe7, 0xaa, + 0xb3, 0x73, 0x97, 0xf5, 0x54, + 0xa7, 0xdf, 0x5f, 0x14, 0x2c, + 0x21, 0xc1, 0xb7, 0x30, 0x3b, + 0x8a, 0x06, 0x26, 0xf1, 0xba, + 0xde, 0xd5, 0xc7, 0x2a, 0x70, + 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, + btcscript.OP_CHECKSIG, + }, + }, + &btcwire.TxOut{ + Value: 4000000000, + PkScript: []byte{ + btcscript.OP_DATA_65, + 0x04, 0x11, 0xdb, 0x93, 0xe1, + 0xdc, 0xdb, 0x8a, 0x01, 0x6b, + 0x49, 0x84, 0x0f, 0x8c, 0x53, + 0xbc, 0x1e, 0xb6, 0x8a, 0x38, + 0x2e, 0x97, 0xb1, 0x48, 0x2e, + 0xca, 0xd7, 0xb1, 0x48, 0xa6, + 0x90, 0x9a, 0x5c, 0xb2, 0xe0, + 0xea, 0xdd, 0xfb, 0x84, 0xcc, + 0xf9, 0x74, 0x44, 0x64, 0xf8, + 0x2e, 0x16, 0x0b, 0xfa, 0x9b, + 0x8b, 0x64, 0xf9, 0xd4, 0xc0, + 0x3f, 0x99, 0x9b, 0x86, 0x43, + 0xf6, 0x56, 0xb4, 0x12, 0xa3, + btcscript.OP_CHECKSIG, + }, + }, + }, + LockTime: 0, + }, + // pubkey header magic byte has been changed to parse wrong. + pkScript: []byte{ + btcscript.OP_DATA_65, + 0x02, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, + 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 0xb6, + 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 0xd7, + 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0, 0xea, + 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64, 0xf8, + 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, + 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, + 0x12, 0xa3, btcscript.OP_CHECKSIG, + }, + idx: 0, + shouldFail: true, + }, // tx 599e47a8114fe098103663029548811d2651991b62397e057f0c863c2bc9f9ea // uses checksig with SigHashNone. txTest{ @@ -766,13 +968,17 @@ func testTx(t *testing.T, test txTest) { err = engine.Execute() if err != nil { + // failed means no specified error + if test.shouldFail == true { + return + } if err != test.err { t.Errorf("Failed to validate %s tx: %v expected %v", test.name, err, test.err) } return } - if test.err != nil { + if test.err != nil || test.shouldFail == true { t.Errorf("%s: expected failure: %v, succeeded", test.name, test.err) } diff --git a/test_coverage.txt b/test_coverage.txt index 228313be..3ccca669 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -114,13 +114,13 @@ github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 96.43% (54/56) +github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) github.com/conformal/btcscript/script.go NewScript 95.24% (20/21) github.com/conformal/btcscript/address.go ScriptToAddress 94.92% (56/59) github.com/conformal/btcscript/script.go parseScript 93.75% (30/32) github.com/conformal/btcscript/script.go Script.Step 89.19% (33/37) github.com/conformal/btcscript/stack.go fromInt 87.50% (14/16) github.com/conformal/btcscript/script.go typeOfScript 83.33% (5/6) -github.com/conformal/btcscript/opcode.go opcodeCheckSig 80.77% (21/26) github.com/conformal/btcscript/opcode.go parsedOpcode.exec 80.00% (4/5) github.com/conformal/btcscript/script.go Script.DisasmScript 80.00% (4/5) github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) @@ -135,5 +135,5 @@ github.com/conformal/btcscript/script.go Script.validPC 60.00% (3/5) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 92.55% (832/899) +github.com/conformal/btcscript -------------------------- 92.99% (836/899) From 5e82baf476ae08663fc010b6992cf9af09b64308 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Wed, 19 Jun 2013 00:38:57 +0100 Subject: [PATCH 008/174] add some basic tests for stack.PopInt() --- stack_test.go | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/stack_test.go b/stack_test.go index cfdf97a3..54ae5110 100644 --- a/stack_test.go +++ b/stack_test.go @@ -170,7 +170,70 @@ var stackTests = []stackTest{ btcscript.StackErrUnderflow, [][]byte{}, }, - // XXX test popInt -> byte format matters here. + { + "popInt 0", + [][]byte{{0x0}}, + func(stack *btcscript.Stack) error { + v, err := stack.PopInt() + if err != nil { + return err + } + if v.Sign() != 0 { + return errors.New("0 != 0 on popInt") + } + return nil + }, + nil, + [][]byte{}, + }, + { + "popInt -0", + [][]byte{{0x80}}, + func(stack *btcscript.Stack) error { + v, err := stack.PopInt() + if err != nil { + return err + } + if v.Sign() != 0 { + return errors.New("-0 != 0 on popInt") + } + return nil + }, + nil, + [][]byte{}, + }, + { + "popInt 1", + [][]byte{{0x01}}, + func(stack *btcscript.Stack) error { + v, err := stack.PopInt() + if err != nil { + return err + } + if v.Cmp(big.NewInt(1)) != 0 { + return errors.New("1 != 1 on popInt") + } + return nil + }, + nil, + [][]byte{}, + }, + { + "popInt 1 leading 0", + [][]byte{{0x00000001}}, + func(stack *btcscript.Stack) error { + v, err := stack.PopInt() + if err != nil { + return err + } + if v.Cmp(big.NewInt(1)) != 0 { + return errors.New("1 != 1 on popInt") + } + return nil + }, + nil, + [][]byte{}, + }, { "dup", [][]byte{{1}}, From 501b7113011af5bb453c3f7f4baccb432984fdab Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Wed, 19 Jun 2013 00:50:18 +0100 Subject: [PATCH 009/174] int.Sign() in go will never return negative for zero. So remove the -0 handling in fromInt, only toInt needs it. --- stack.go | 5 ----- test_coverage.txt | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/stack.go b/stack.go index a1efa8f9..952d5bdb 100644 --- a/stack.go +++ b/stack.go @@ -51,11 +51,6 @@ func fromInt(v *big.Int) []byte { // Int.Bytes() trims leading zeros for us, so we don't have to. b := v.Bytes() if len(b) == 0 { - // negative 0 - if negative { - return []byte{0x80} - } - // normal 0 return []byte{} } arr := make([]byte, len(b)) diff --git a/test_coverage.txt b/test_coverage.txt index 3ccca669..4734c5c1 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -118,8 +118,8 @@ github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) github.com/conformal/btcscript/script.go NewScript 95.24% (20/21) github.com/conformal/btcscript/address.go ScriptToAddress 94.92% (56/59) github.com/conformal/btcscript/script.go parseScript 93.75% (30/32) +github.com/conformal/btcscript/stack.go fromInt 92.86% (13/14) github.com/conformal/btcscript/script.go Script.Step 89.19% (33/37) -github.com/conformal/btcscript/stack.go fromInt 87.50% (14/16) github.com/conformal/btcscript/script.go typeOfScript 83.33% (5/6) github.com/conformal/btcscript/opcode.go parsedOpcode.exec 80.00% (4/5) github.com/conformal/btcscript/script.go Script.DisasmScript 80.00% (4/5) @@ -135,5 +135,5 @@ github.com/conformal/btcscript/script.go Script.validPC 60.00% (3/5) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 92.99% (836/899) +github.com/conformal/btcscript -------------------------- 93.09% (835/897) From 625541e202a1d7a2916fcf08e180161ec6331574 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Wed, 19 Jun 2013 01:06:02 +0100 Subject: [PATCH 010/174] add some testing for byte format in stack.PushInt() should verify all the formats now. pain causes endian little. --- stack_test.go | 52 +++++++++++++++++++++++++++++++ test_coverage.txt | 78 +++++++++++++++++++++++------------------------ 2 files changed, 91 insertions(+), 39 deletions(-) diff --git a/stack_test.go b/stack_test.go index 54ae5110..942a227d 100644 --- a/stack_test.go +++ b/stack_test.go @@ -234,6 +234,58 @@ var stackTests = []stackTest{ nil, [][]byte{}, }, + { + "PushInt 0", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushInt(big.NewInt(0)) + return nil + }, + nil, + [][]byte{{}}, + }, + { + "PushInt 1", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushInt(big.NewInt(1)) + return nil + }, + nil, + [][]byte{{0x1}}, + }, + { + "PushInt -1", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushInt(big.NewInt(-1)) + return nil + }, + nil, + [][]byte{{0x81}}, + }, + { + "PushInt two bytes", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushInt(big.NewInt(256)) + return nil + }, + nil, + // little endian.. *sigh* + [][]byte{{0x00, 0x01}}, + }, + { + "PushInt leading zeros", + [][]byte{}, + func(stack *btcscript.Stack) error { + // this will have the highbit set + stack.PushInt(big.NewInt(128)) + return nil + }, + nil, + [][]byte{{0x80, 0x00 }}, + }, { "dup", [][]byte{{1}}, diff --git a/test_coverage.txt b/test_coverage.txt index 4734c5c1..b0f06e33 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -1,54 +1,55 @@ github.com/conformal/btcscript/stack.go asInt 100.00% (18/18) +github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) +github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12) -github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) +github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) +github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) -github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) -github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) +github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) -github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) +github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) @@ -61,20 +62,20 @@ github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) github.com/conformal/btcscript/script.go unparseScript 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) -github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) -github.com/conformal/btcscript/script.go setStack 100.00% (3/3) +github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) -github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) -github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) -github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) +github.com/conformal/btcscript/script.go setStack 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) +github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) github.com/conformal/btcscript/opcode.go init 100.00% (1/1) @@ -86,10 +87,10 @@ github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) @@ -112,28 +113,27 @@ github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 96.43% (54/56) github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) github.com/conformal/btcscript/script.go NewScript 95.24% (20/21) github.com/conformal/btcscript/address.go ScriptToAddress 94.92% (56/59) github.com/conformal/btcscript/script.go parseScript 93.75% (30/32) -github.com/conformal/btcscript/stack.go fromInt 92.86% (13/14) github.com/conformal/btcscript/script.go Script.Step 89.19% (33/37) github.com/conformal/btcscript/script.go typeOfScript 83.33% (5/6) github.com/conformal/btcscript/opcode.go parsedOpcode.exec 80.00% (4/5) github.com/conformal/btcscript/script.go Script.DisasmScript 80.00% (4/5) -github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) github.com/conformal/btcscript/script.go Script.curPC 75.00% (3/4) -github.com/conformal/btcscript/script.go Script.DisasmPC 75.00% (3/4) github.com/conformal/btcscript/script.go isPushOnly 75.00% (3/4) +github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) +github.com/conformal/btcscript/script.go Script.DisasmPC 75.00% (3/4) github.com/conformal/btcscript/script.go Script.calcScriptHash 71.43% (25/35) github.com/conformal/btcscript/script.go Script.CheckErrorCondition 71.43% (10/14) github.com/conformal/btcscript/script.go isMultiSig 61.54% (8/13) -github.com/conformal/btcscript/opcode.go opcodeSha1 60.00% (3/5) github.com/conformal/btcscript/script.go Script.validPC 60.00% (3/5) +github.com/conformal/btcscript/opcode.go opcodeSha1 60.00% (3/5) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 93.09% (835/897) +github.com/conformal/btcscript -------------------------- 93.20% (836/897) From 8035de426b37952dab8654a18dc9b04099dcc7c9 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Wed, 19 Jun 2013 23:31:44 +0100 Subject: [PATCH 011/174] Check that the pc validation code works ok. Add a testing only interface to set the pc and set it to a few invalid settings to check that step and disasmPC all blow up correctly. --- internal_test.go | 7 ++++ script_test.go | 72 +++++++++++++++++++++++++++++++++ test_coverage.txt | 100 +++++++++++++++++++++++----------------------- 3 files changed, 129 insertions(+), 50 deletions(-) diff --git a/internal_test.go b/internal_test.go index a4196b31..239456df 100644 --- a/internal_test.go +++ b/internal_test.go @@ -42,3 +42,10 @@ func TstTypeOfScript(script []byte) TstScriptType { } return TstScriptType(typeOfScript(pops)) } + +// TestSetPC allows the test modules to set the program counter to whatever they +// want. +func (s *Script) TstSetPC(script, off int) { + s.scriptidx = script + s.scriptoff = off +} diff --git a/script_test.go b/script_test.go index 9f65969a..8e887f8e 100644 --- a/script_test.go +++ b/script_test.go @@ -1264,3 +1264,75 @@ func TestScriptTypes(t *testing.T) { testScriptType(t, &scriptTypeTests[i]) } } + +// This test sets the pc to a deliberately bad result then confirms that Step() +// and Disasm fail correctly. +func TestBadPC(t *testing.T) { + type pcTest struct { + script, off int + } + pcTests := []pcTest{ + pcTest{ + script:2, + off:0, + }, + pcTest{ + script: 0, + off: 2, + }, + } + // tx with almost empty scripts. + tx := &btcwire.MsgTx{ + Version: 1, + TxIn: []*btcwire.TxIn{ + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash([32]byte{ + 0xc9, 0x97, 0xa5, 0xe5, + 0x6e, 0x10, 0x41, 0x02, + 0xfa, 0x20, 0x9c, 0x6a, + 0x85, 0x2d, 0xd9, 0x06, + 0x60, 0xa2, 0x0b, 0x2d, + 0x9c, 0x35, 0x24, 0x23, + 0xed, 0xce, 0x25, 0x85, + 0x7f, 0xcd, 0x37, 0x04, + }), + Index: 0, + }, + SignatureScript: []uint8{btcscript.OP_NOP}, + Sequence: 4294967295, + }, + }, + TxOut: []*btcwire.TxOut{ + &btcwire.TxOut{ + Value: 1000000000, + PkScript: []byte{}, + }, + }, + LockTime: 0, + } + pkScript := []byte{btcscript.OP_NOP} + + for _, test := range pcTests { + engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript, + pkScript, 0, tx, 70001, false) + if err != nil { + t.Errorf("Failed to create script: %v", err) + } + + // set to after all scripts + engine.TstSetPC(test.script, test.off) + + _, err = engine.Step() + if err == nil { + t.Errorf("Step with invalid pc (%v) succeeds!", test) + continue + } + + _, err = engine.DisasmPC() + if err == nil { + t.Errorf("DisasmPC with invalid pc (%v) succeeds!", + test) + } + } +} diff --git a/test_coverage.txt b/test_coverage.txt index b0f06e33..83ce72b9 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -2,54 +2,55 @@ github.com/conformal/btcscript/stack.go asInt 100.00% (18/18) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) -github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12) -github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12) +github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) +github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) -github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) +github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) -github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) -github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) +github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) +github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) -github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) @@ -61,50 +62,48 @@ github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) github.com/conformal/btcscript/script.go unparseScript 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) -github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) github.com/conformal/btcscript/script.go setStack 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) -github.com/conformal/btcscript/opcode.go init 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) -github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) +github.com/conformal/btcscript/opcode.go init 100.00% (1/1) github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) -github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) +github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) github.com/conformal/btcscript/log.go init 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) @@ -113,27 +112,28 @@ github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) +github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 96.43% (54/56) github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) github.com/conformal/btcscript/script.go NewScript 95.24% (20/21) github.com/conformal/btcscript/address.go ScriptToAddress 94.92% (56/59) github.com/conformal/btcscript/script.go parseScript 93.75% (30/32) -github.com/conformal/btcscript/script.go Script.Step 89.19% (33/37) +github.com/conformal/btcscript/script.go Script.Step 91.89% (34/37) github.com/conformal/btcscript/script.go typeOfScript 83.33% (5/6) -github.com/conformal/btcscript/opcode.go parsedOpcode.exec 80.00% (4/5) github.com/conformal/btcscript/script.go Script.DisasmScript 80.00% (4/5) -github.com/conformal/btcscript/script.go Script.curPC 75.00% (3/4) +github.com/conformal/btcscript/opcode.go parsedOpcode.exec 80.00% (4/5) github.com/conformal/btcscript/script.go isPushOnly 75.00% (3/4) github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) -github.com/conformal/btcscript/script.go Script.DisasmPC 75.00% (3/4) github.com/conformal/btcscript/script.go Script.calcScriptHash 71.43% (25/35) github.com/conformal/btcscript/script.go Script.CheckErrorCondition 71.43% (10/14) github.com/conformal/btcscript/script.go isMultiSig 61.54% (8/13) -github.com/conformal/btcscript/script.go Script.validPC 60.00% (3/5) github.com/conformal/btcscript/opcode.go opcodeSha1 60.00% (3/5) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 93.20% (836/897) +github.com/conformal/btcscript -------------------------- 93.76% (841/897) From bac455cdd2326897b3e56539081cdd19212504e9 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Thu, 20 Jun 2013 00:30:34 +0100 Subject: [PATCH 012/174] Fix reversed test bug with the max operations handling We were counting the number of push ops instead of the number of non push ops. Add tests that found this (checking tha the max operations check fires). --- opcode.go | 2 +- opcode_test.go | 419 ++++++++++++++++++++++++++++++++++++++++++++++ test_coverage.txt | 68 ++++---- 3 files changed, 454 insertions(+), 35 deletions(-) diff --git a/opcode.go b/opcode.go index 613b8361..613fd74f 100644 --- a/opcode.go +++ b/opcode.go @@ -654,7 +654,7 @@ func (pop *parsedOpcode) exec(s *Script) error { // *sigh* bitcoind pretty much mandates that we violate layering here. // Any opcode that isn't just adding data to the stack counts here // as an operation. - if pop.opcode.value < OP_16 { + if pop.opcode.value > OP_16 { s.numOps++ if s.numOps > MaxOpsPerScript { return StackErrTooManyOperations diff --git a/opcode_test.go b/opcode_test.go index 3970b10d..dbbecd30 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -2400,6 +2400,425 @@ var detailedTests = []detailedTest{ expectedReturn: btcscript.StackErrVerifyFailed, disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 OP_1 OP_1 OP_CHECKMULTISIGVERIFY", }, + { + // 201 operations + one push, should just fit limits + name: "max operations", + script: []byte{btcscript.OP_1, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + }, + after: [][]byte{{1}, {1}}, + disassembly: "OP_1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP", + }, + { + // 202 operations + one push + name: "too many operations", + script: []byte{btcscript.OP_1, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + }, + expectedReturn: btcscript.StackErrTooManyOperations, + disassembly: "OP_1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP", + }, { name: "OP_CAT disabled", script: []byte{btcscript.OP_CAT}, diff --git a/test_coverage.txt b/test_coverage.txt index 83ce72b9..cd1b94d6 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -2,55 +2,56 @@ github.com/conformal/btcscript/stack.go asInt 100.00% (18/18) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) +github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12) github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) -github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12) -github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) +github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) +github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) +github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) -github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) +github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) -github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) +github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) -github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) +github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) @@ -65,38 +66,35 @@ github.com/conformal/btcscript/script.go unparseScript 100.00% (4/4) github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) -github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) -github.com/conformal/btcscript/script.go setStack 100.00% (3/3) +github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) +github.com/conformal/btcscript/script.go setStack 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) github.com/conformal/btcscript/opcode.go init 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) @@ -113,10 +111,13 @@ github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) +github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 96.43% (54/56) github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) github.com/conformal/btcscript/script.go NewScript 95.24% (20/21) @@ -125,7 +126,6 @@ github.com/conformal/btcscript/script.go parseScript 93.75% (30/32) github.com/conformal/btcscript/script.go Script.Step 91.89% (34/37) github.com/conformal/btcscript/script.go typeOfScript 83.33% (5/6) github.com/conformal/btcscript/script.go Script.DisasmScript 80.00% (4/5) -github.com/conformal/btcscript/opcode.go parsedOpcode.exec 80.00% (4/5) github.com/conformal/btcscript/script.go isPushOnly 75.00% (3/4) github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) github.com/conformal/btcscript/script.go Script.calcScriptHash 71.43% (25/35) @@ -135,5 +135,5 @@ github.com/conformal/btcscript/opcode.go opcodeSha1 60.00% (3/5) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 93.76% (841/897) +github.com/conformal/btcscript -------------------------- 93.87% (842/897) From 25624bc6a707df97ea0cec95b9f4b09ab3bb8fda Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Thu, 20 Jun 2013 01:21:12 +0100 Subject: [PATCH 013/174] check that OP_CHECK_MULTISIG also triggers on too many ops --- opcode_test.go | 214 ++++++++++++++++++++++++++++++++++++++++++++++ test_coverage.txt | 4 +- 2 files changed, 216 insertions(+), 2 deletions(-) diff --git a/opcode_test.go b/opcode_test.go index dbbecd30..b3ce43d2 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -2819,6 +2819,220 @@ var detailedTests = []detailedTest{ expectedReturn: btcscript.StackErrTooManyOperations, disassembly: "OP_1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP", }, + { + // 202 operations + one push + name: "too many operations multisig", + script: []byte{btcscript.OP_1, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_1, + btcscript.OP_1, + btcscript.OP_1, + btcscript.OP_1, + btcscript.OP_2, + btcscript.OP_CHECK_MULTISIG, + }, + expectedReturn: btcscript.StackErrTooManyOperations, + disassembly: "OP_1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_1 OP_1 OP_1 OP_1 OP_2 OP_CHECK_MULTISIG", + }, { name: "OP_CAT disabled", script: []byte{btcscript.OP_CAT}, diff --git a/test_coverage.txt b/test_coverage.txt index cd1b94d6..34e69f39 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -118,7 +118,7 @@ github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 96.43% (54/56) +github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.21% (55/56) github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) github.com/conformal/btcscript/script.go NewScript 95.24% (20/21) github.com/conformal/btcscript/address.go ScriptToAddress 94.92% (56/59) @@ -135,5 +135,5 @@ github.com/conformal/btcscript/opcode.go opcodeSha1 60.00% (3/5) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 93.87% (842/897) +github.com/conformal/btcscript -------------------------- 93.98% (843/897) From 421a213a4f00a5e807e15092371c15bf933254b2 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Thu, 20 Jun 2013 20:01:17 +0100 Subject: [PATCH 014/174] Stop modifying the passed tx in NewScript. The only time we need to zero out scripts is for calcScriptHash which operates on a deep copy anyway. This should make the tx passed to us unmodified now. --- script.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/script.go b/script.go index 9d68e4d6..8a1bf604 100644 --- a/script.go +++ b/script.go @@ -325,9 +325,6 @@ func NewScript(scriptSig []byte, scriptPubKey []byte, txidx int, tx *btcwire.Msg m.bip16 = true } - for i, _ := range tx.TxIn { - tx.TxIn[i].SignatureScript = []byte{} - } m.tx = *tx m.txidx = txidx m.pver = pver From 03696a88749d1fb99c46612e0a8de8f2244779f1 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Thu, 20 Jun 2013 18:07:44 +0100 Subject: [PATCH 015/174] Add functions to count the number of signature operations in a script. To be usd for validation. Most of the codepaths teste, a few tests missing for cases needed tests in the validation codepaths too. To be worked on in tree. --- opcode_test.go | 110 ++++++++++++++++++++++++++++++++++++++++++++++ script.go | 84 +++++++++++++++++++++++++++++++++++ script_test.go | 29 ++++++++++++ test_coverage.txt | 99 +++++++++++++++++++++-------------------- 4 files changed, 274 insertions(+), 48 deletions(-) diff --git a/opcode_test.go b/opcode_test.go index b3ce43d2..298292c5 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -542,6 +542,8 @@ type detailedTest struct { altafter [][]byte disassembly string disassemblyerr error + nSigOps int // should have same return as disassembly error + nPreciseSigOps int // should have same return as disassembly error } var detailedTests = []detailedTest{ @@ -2115,12 +2117,16 @@ var detailedTests = []detailedTest{ script: []byte{btcscript.OP_1, btcscript.OP_CHECKSIG}, expectedReturn: btcscript.StackErrUnderflow, disassembly: "OP_1 OP_CHECKSIG", + nSigOps: 1, + nPreciseSigOps: 1, }, { name: "OP_CHECKSIG no arg", script: []byte{btcscript.OP_CHECKSIG}, expectedReturn: btcscript.StackErrUnderflow, disassembly: "OP_CHECKSIG", + nSigOps: 1, + nPreciseSigOps: 1, }, { name: "OP_CHECKSIGVERIFY one arg", @@ -2128,18 +2134,24 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECKSIGVERIFY}, expectedReturn: btcscript.StackErrUnderflow, disassembly: "OP_1 OP_CHECKSIGVERIFY", + nSigOps: 1, + nPreciseSigOps: 1, }, { name: "OP_CHECKSIGVERIFY no arg", script: []byte{btcscript.OP_CHECKSIGVERIFY}, expectedReturn: btcscript.StackErrUnderflow, disassembly: "OP_CHECKSIGVERIFY", + nSigOps: 1, + nPreciseSigOps: 1, }, { name: "OP_CHECK_MULTISIG no args", script: []byte{btcscript.OP_CHECK_MULTISIG}, expectedReturn: btcscript.StackErrUnderflow, disassembly: "OP_CHECK_MULTISIG", + nSigOps: 20, + nPreciseSigOps: 20, }, { name: "OP_CHECK_MULTISIG huge number", @@ -2148,6 +2160,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECK_MULTISIG}, expectedReturn: btcscript.StackErrNumberTooBig, disassembly: "010203040506070809 OP_CHECK_MULTISIG", + nSigOps: 20, + nPreciseSigOps: 20, }, { name: "OP_CHECK_MULTISIG too many keys", @@ -2155,6 +2169,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECK_MULTISIG}, expectedReturn: btcscript.StackErrTooManyPubkeys, disassembly: "15 OP_CHECK_MULTISIG", + nSigOps: 20, + nPreciseSigOps: 20, }, { name: "OP_CHECK_MULTISIG lying about pubkeys", @@ -2162,6 +2178,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECK_MULTISIG}, expectedReturn: btcscript.StackErrUnderflow, disassembly: "OP_1 OP_CHECK_MULTISIG", + nSigOps: 20, + nPreciseSigOps: 1, }, { // pubkey comes from blockchain @@ -2180,6 +2198,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECK_MULTISIG}, expectedReturn: btcscript.StackErrUnderflow, disassembly: "04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECK_MULTISIG", + nSigOps: 20, + nPreciseSigOps: 1, }, { // pubkey comes from blockchain @@ -2200,6 +2220,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECK_MULTISIG}, expectedReturn: btcscript.StackErrNumberTooBig, disassembly: "010203040506070809 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECK_MULTISIG", + nSigOps: 20, + nPreciseSigOps: 1, }, { name: "OP_CHECK_MULTISIG too few sigs", @@ -2217,6 +2239,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECK_MULTISIG}, expectedReturn: btcscript.StackErrUnderflow, disassembly: "OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECK_MULTISIG", + nSigOps: 20, + nPreciseSigOps: 1, }, { // pubkey and sig comes from blockchain, are unrelated @@ -2245,6 +2269,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECK_MULTISIG}, after: [][]byte{{0}}, disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECK_MULTISIG", + nSigOps: 20, + nPreciseSigOps: 1, }, { // invalid pubkey means that it fails to validate, not an @@ -2266,6 +2292,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECK_MULTISIG}, after: [][]byte{{0}}, disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 OP_1 OP_1 OP_CHECK_MULTISIG", + nSigOps: 20, + nPreciseSigOps: 1, }, // XXX(oga) Test multisig when extra arg is missing. needs valid sig. // disabled opcodes @@ -2274,6 +2302,8 @@ var detailedTests = []detailedTest{ script: []byte{btcscript.OP_CHECKMULTISIGVERIFY}, expectedReturn: btcscript.StackErrUnderflow, disassembly: "OP_CHECKMULTISIGVERIFY", + nSigOps: 20, + nPreciseSigOps: 20, }, { name: "OP_CHECKMULTISIGVERIFY huge number", @@ -2282,6 +2312,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECKMULTISIGVERIFY}, expectedReturn: btcscript.StackErrNumberTooBig, disassembly: "010203040506070809 OP_CHECKMULTISIGVERIFY", + nSigOps: 20, + nPreciseSigOps: 20, }, { name: "OP_CHECKMULTISIGVERIFY too many keys", @@ -2289,6 +2321,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECKMULTISIGVERIFY}, expectedReturn: btcscript.StackErrTooManyPubkeys, disassembly: "15 OP_CHECKMULTISIGVERIFY", + nSigOps: 20, + nPreciseSigOps: 20, }, { name: "OP_CHECKMULTISIGVERIFY lying about pubkeys", @@ -2296,6 +2330,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECKMULTISIGVERIFY}, expectedReturn: btcscript.StackErrUnderflow, disassembly: "OP_1 OP_CHECKMULTISIGVERIFY", + nSigOps: 20, + nPreciseSigOps: 1, }, { // pubkey comes from blockchain @@ -2314,6 +2350,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECKMULTISIGVERIFY}, expectedReturn: btcscript.StackErrUnderflow, disassembly: "04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIGVERIFY", + nSigOps: 20, + nPreciseSigOps: 1, }, { name: "OP_CHECKMULTISIGVERIFY sigs huge no", @@ -2333,6 +2371,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECKMULTISIGVERIFY}, expectedReturn: btcscript.StackErrNumberTooBig, disassembly: "010203040506070809 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIGVERIFY", + nSigOps: 20, + nPreciseSigOps: 1, }, { name: "OP_CHECKMULTISIGVERIFY too few sigs", @@ -2350,6 +2390,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECKMULTISIGVERIFY}, expectedReturn: btcscript.StackErrUnderflow, disassembly: "OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIGVERIFY", + nSigOps: 20, + nPreciseSigOps: 1, }, { // pubkey and sig comes from blockchain, are unrelated @@ -2378,6 +2420,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECKMULTISIGVERIFY}, expectedReturn: btcscript.StackErrVerifyFailed, disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIGVERIFY", + nSigOps: 20, + nPreciseSigOps: 1, }, { // invalid pubkey means that it fails to validate, not an @@ -2399,6 +2443,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECKMULTISIGVERIFY}, expectedReturn: btcscript.StackErrVerifyFailed, disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 OP_1 OP_1 OP_CHECKMULTISIGVERIFY", + nSigOps: 20, + nPreciseSigOps: 1, }, { // 201 operations + one push, should just fit limits @@ -3032,6 +3078,8 @@ var detailedTests = []detailedTest{ }, expectedReturn: btcscript.StackErrTooManyOperations, disassembly: "OP_1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_1 OP_1 OP_1 OP_1 OP_2 OP_CHECK_MULTISIG", + nSigOps: 20, + nPreciseSigOps: 2, }, { name: "OP_CAT disabled", @@ -3735,3 +3783,65 @@ func TestDisasmStrings(t *testing.T) { testDisasmString(t, &detailedTests[i]) } } + +// A basic test of GetSigOpCount for most opcodes, we do this by +// running the same test for every one of the detailed tests. Since +// disassembly errors are always parse errors, and so are +// sigops count errors we use the same error code. +// While this isn't as precise as using full transaction scripts, this gives +// us coverage over a wider range of opcodes. +func TestSigOps(t *testing.T) { + for _, test := range detailedTests { + count, err := btcscript.GetSigOpCount(test.script) + if err != nil { + if err != test.disassemblyerr { + t.Errorf("%s: unexpected error. exp \"%v\""+ + "got \"%v\"", test.name, + test.disassemblyerr, err) + } + continue + } + if test.disassemblyerr != nil { + t.Errorf("%s: no error when expected \"%v\"", + test.name, test.disassemblyerr) + continue + } + if count != test.nSigOps { + t.Errorf("%s: expected count of %d, got %d", test.name, + test.nSigOps, count) + + } + } +} + +// A basic test of GetPreciseSigOpCount for most opcodes, we do this by +// running the same test for every one of the detailed tests with a fake +// sigscript. Sicne disassembly errors are always parse errors, and so are +// sigops count errors we use the same error code. +// While this isn't as precise as using full transaction scripts, this gives +// us coverage over a wider range of opcodes. See script_test.go for tests +// using real transactions to provide a bit more coverage. +func TestPreciseSigOps(t *testing.T) { + for _, test := range detailedTests { + count, err := btcscript.GetPreciseSigOpCount( + []byte{btcscript.OP_1}, test.script, false) + if err != nil { + if err != test.disassemblyerr { + t.Errorf("%s: unexpected error. exp \"%v\""+ + "got \"%v\"", test.name, + test.disassemblyerr, err) + } + continue + } + if test.disassemblyerr != nil { + t.Errorf("%s: no error when expected \"%v\"", + test.name, test.disassemblyerr) + continue + } + if count != test.nPreciseSigOps { + t.Errorf("%s: expected count of %d, got %d", test.name, + test.nPreciseSigOps, count) + + } + } +} diff --git a/script.go b/script.go index 8a1bf604..8fc9e3dc 100644 --- a/script.go +++ b/script.go @@ -715,3 +715,87 @@ func (s *Script) GetAltStack() [][]byte { func (s *Script) SetAltStack(data [][]byte) { setStack(&s.astack, data) } + +// GetSigOpCount provides a quick count of the number of signature operations +// in a script. a CHECKSIG operations counts for 1, and a CHECK_MULTISIG for 20. +func GetSigOpCount(script [] byte) (int, error) { + pops, err := parseScript(script) + if err != nil { + return 0, err + } + + return getSigOpCount(pops, false), nil +} + +// GetPreciseSigOpCount returns the number of signature operations in +// scriptPubKey. If bip16 is true then scriptSig may be searched for the +// Pay-To-Script-Hash script in order to find the precise number of signature +// operations in the transaction. +func GetPreciseSigOpCount(scriptSig, scriptPubKey []byte, bip16 bool) (int, error) { + pops, err := parseScript(scriptPubKey) + if err != nil { + return 0, err + } + // non P2SH transactions just treated as normal. + if !(bip16 && isScriptHash(pops)) { + return getSigOpCount(pops, true), nil + } + + // Ok so this is P2SH, get the contained script and count it.. + + sigPops, err := parseScript(scriptSig) + if err != nil { + return 0, err + } + if !isPushOnly(sigPops) || len(sigPops) == 0 { + return 0, nil + } + + shScript := sigPops[len(sigPops) - 1].data + // Means that sigPops is jus OP_1 - OP_16, no sigops there. + if shScript == nil { + return 0, nil + } + + shPops, err := parseScript(shScript) + if err != nil { + return 0, err + } + + return getSigOpCount(shPops, true), nil +} + +// getSigOpCount is the implementation function for counting the number of +// signature operations in the script provided by pops. If precise mode is +// requested then we attempt to count the number of operations for a multisig +// op. Otherwise we use the maximum. +func getSigOpCount(pops []parsedOpcode, precise bool) int { + nSigs := 0 + for i, pop := range pops { + switch pop.opcode.value { + case OP_CHECKSIG: + fallthrough; + case OP_CHECKSIGVERIFY: + nSigs++ + case OP_CHECK_MULTISIG: + fallthrough; + case OP_CHECKMULTISIGVERIFY: + // If we are being precise then look for familiar + // patterns for multisig, for now all we recognise is + // OP_1 - OP_16 to signify the number of pubkeys. + // Otherwise, we use the max of 20. + if precise && i > 0 && + pops[i - 1].opcode.value >= OP_1 && + pops[i - 1].opcode.value <= OP_16 { + nSigs += int(pops[i-1].opcode.value - + (OP_1 - 1)) + } else { + nSigs += MaxPubKeysPerMultiSig + } + default: + // not a sigop. + } + } + + return nSigs +} diff --git a/script_test.go b/script_test.go index 8e887f8e..45f1029f 100644 --- a/script_test.go +++ b/script_test.go @@ -19,6 +19,7 @@ type txTest struct { bip16 bool err error shouldFail bool + nSigOps int } var txTests = []txTest{ @@ -121,6 +122,7 @@ var txTests = []txTest{ 0x12, 0xa3, btcscript.OP_CHECKSIG, }, idx: 0, + nSigOps: 1, }, // Previous test with the value of one output changed. txTest{ @@ -221,6 +223,7 @@ var txTests = []txTest{ }, idx: 0, err: btcscript.StackErrScriptFailed, + nSigOps: 1, }, txTest{ name: "CheckSig invalid signature", @@ -322,6 +325,7 @@ var txTests = []txTest{ }, idx: 0, shouldFail: true, + nSigOps: 1, }, txTest{ name: "CheckSig invalid pubkey", @@ -422,6 +426,7 @@ var txTests = []txTest{ }, idx: 0, shouldFail: true, + nSigOps: 1, }, // tx 599e47a8114fe098103663029548811d2651991b62397e057f0c863c2bc9f9ea // uses checksig with SigHashNone. @@ -523,6 +528,7 @@ var txTests = []txTest{ }, idx: 0, bip16: true, // after threshold + nSigOps: 1, }, // tx 51bf528ecf3c161e7c021224197dbe84f9a8564212f6207baa014c01a1668e1e // first instance of an AnyoneCanPay signature in the blockchain @@ -646,6 +652,7 @@ var txTests = []txTest{ }, idx: 0, bip16: true, // after threshold + nSigOps: 1, }, // tx 6d36bc17e947ce00bb6f12f8e7a56a1585c5a36188ffa2b05e10b4743273a74b // Uses OP_CODESEPARATOR and OP_CHECKMULTISIG @@ -768,6 +775,7 @@ var txTests = []txTest{ }, idx: 1, bip16: false, + nSigOps: 0, // multisig is in the pkScript! }, // same as previous but with one byte changed to make signature fail txTest{ @@ -890,6 +898,7 @@ var txTests = []txTest{ idx: 1, bip16: false, err: btcscript.StackErrScriptFailed, + nSigOps: 0, // multisig is in the pkScript! }, // tx e5779b9e78f9650debc2893fd9636d827b26b4ddfa6a8172fe8708c924f5c39d // First P2SH transaction in the blockchain @@ -948,6 +957,7 @@ var txTests = []txTest{ }, idx: 0, bip16: true, + nSigOps: 0, // no signature ops in the pushed script. }, } @@ -990,6 +1000,25 @@ func TestTX(t *testing.T) { } } +func TestGetPreciseSignOps(t *testing.T) { + for _, test := range txTests { + count, err := btcscript.GetPreciseSigOpCount( + test.tx.TxIn[test.idx].SignatureScript, test.pkScript, + test.bip16) + // all tx currently parse + if err != nil { + t.Errorf("%s: unexpected error. got \"%v\"", + test.name, err) + continue + } + if count != test.nSigOps { + t.Errorf("%s: expected count of %d, got %d", test.name, + test.nSigOps, count) + + } + } +} + type removeOpcodeTest struct { name string before []byte diff --git a/test_coverage.txt b/test_coverage.txt index 34e69f39..3d71e051 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -2,56 +2,57 @@ github.com/conformal/btcscript/stack.go asInt 100.00% (18/18) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) -github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12) -github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) +github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12) +github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) +github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) +github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) -github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) -github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) +github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) -github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) +github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) @@ -66,43 +67,47 @@ github.com/conformal/btcscript/script.go unparseScript 100.00% (4/4) github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) +github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (4/4) github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) +github.com/conformal/btcscript/script.go setStack 100.00% (3/3) github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) -github.com/conformal/btcscript/script.go setStack 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) -github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) -github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) +github.com/conformal/btcscript/opcode.go init 100.00% (1/1) +github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) -github.com/conformal/btcscript/opcode.go init 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) +github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) -github.com/conformal/btcscript/log.go init 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/conformal/btcscript/log.go init 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) @@ -112,22 +117,20 @@ github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) -github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.21% (55/56) github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) -github.com/conformal/btcscript/script.go NewScript 95.24% (20/21) github.com/conformal/btcscript/address.go ScriptToAddress 94.92% (56/59) +github.com/conformal/btcscript/script.go NewScript 94.74% (18/19) github.com/conformal/btcscript/script.go parseScript 93.75% (30/32) github.com/conformal/btcscript/script.go Script.Step 91.89% (34/37) github.com/conformal/btcscript/script.go typeOfScript 83.33% (5/6) github.com/conformal/btcscript/script.go Script.DisasmScript 80.00% (4/5) -github.com/conformal/btcscript/script.go isPushOnly 75.00% (3/4) +github.com/conformal/btcscript/script.go GetPreciseSigOpCount 77.78% (14/18) github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) +github.com/conformal/btcscript/script.go isPushOnly 75.00% (3/4) github.com/conformal/btcscript/script.go Script.calcScriptHash 71.43% (25/35) github.com/conformal/btcscript/script.go Script.CheckErrorCondition 71.43% (10/14) github.com/conformal/btcscript/script.go isMultiSig 61.54% (8/13) @@ -135,5 +138,5 @@ github.com/conformal/btcscript/opcode.go opcodeSha1 60.00% (3/5) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 93.98% (843/897) +github.com/conformal/btcscript -------------------------- 93.74% (869/927) From 8fe24958bb3cf21ee66663bd1b3e3b2f73df7703 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Fri, 21 Jun 2013 01:33:38 +0100 Subject: [PATCH 016/174] Test the unfinished condition of CheckErrorCondition --- script_test.go | 88 +++++++++++++++++++++++++++++++++++++++++++++++ test_coverage.txt | 6 ++-- 2 files changed, 91 insertions(+), 3 deletions(-) diff --git a/script_test.go b/script_test.go index 45f1029f..69642531 100644 --- a/script_test.go +++ b/script_test.go @@ -1365,3 +1365,91 @@ func TestBadPC(t *testing.T) { } } } + +// Most codepaths in CheckErrorCondition() are testd elsewhere, this tests +// the execute early test. +func TestCheckErrorCondition(t *testing.T) { + // tx with almost empty scripts. + tx := &btcwire.MsgTx{ + Version: 1, + TxIn: []*btcwire.TxIn{ + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash([32]byte{ + 0xc9, 0x97, 0xa5, 0xe5, + 0x6e, 0x10, 0x41, 0x02, + 0xfa, 0x20, 0x9c, 0x6a, + 0x85, 0x2d, 0xd9, 0x06, + 0x60, 0xa2, 0x0b, 0x2d, + 0x9c, 0x35, 0x24, 0x23, + 0xed, 0xce, 0x25, 0x85, + 0x7f, 0xcd, 0x37, 0x04, + }), + Index: 0, + }, + SignatureScript: []uint8{}, + Sequence: 4294967295, + }, + }, + TxOut: []*btcwire.TxOut{ + &btcwire.TxOut{ + Value: 1000000000, + PkScript: []byte{}, + }, + }, + LockTime: 0, + } + pkScript := []byte{ + btcscript.OP_NOP, + btcscript.OP_NOP, + btcscript.OP_NOP, + btcscript.OP_NOP, + btcscript.OP_NOP, + btcscript.OP_NOP, + btcscript.OP_NOP, + btcscript.OP_NOP, + btcscript.OP_NOP, + btcscript.OP_NOP, + btcscript.OP_TRUE, + } + + engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript, pkScript, + 0, tx, 70001, false) + if err != nil { + t.Errorf("failed to create script: %v", err) + } + + for i := 0; i < len(pkScript) - 1; i++ { + done, err := engine.Step() + if err != nil { + t.Errorf("failed to step %dth time: %v", i, err) + return + } + if done { + t.Errorf("finshed early on %dth time", i) + return + } + + err = engine.CheckErrorCondition() + if err != btcscript.StackErrScriptUnfinished { + t.Errorf("got unexepected error %v on %dth iteration", + err, i) + return + } + } + done, err := engine.Step() + if err != nil { + t.Errorf("final step failed %v", err) + return + } + if !done { + t.Errorf("final step isn't done!") + return + } + + err = engine.CheckErrorCondition() + if err != nil { + t.Errorf("unexpected error %v on final check", err) + } +} + diff --git a/test_coverage.txt b/test_coverage.txt index 3d71e051..f3287f46 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -128,15 +128,15 @@ github.com/conformal/btcscript/script.go parseScript 93.75% (30/32) github.com/conformal/btcscript/script.go Script.Step 91.89% (34/37) github.com/conformal/btcscript/script.go typeOfScript 83.33% (5/6) github.com/conformal/btcscript/script.go Script.DisasmScript 80.00% (4/5) -github.com/conformal/btcscript/script.go GetPreciseSigOpCount 77.78% (14/18) +github.com/conformal/btcscript/script.go Script.CheckErrorCondition 78.57% (11/14) +github.com/conformal/btcscript/script.go GetPreciseSigOpCount 76.47% (13/17) github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) github.com/conformal/btcscript/script.go isPushOnly 75.00% (3/4) github.com/conformal/btcscript/script.go Script.calcScriptHash 71.43% (25/35) -github.com/conformal/btcscript/script.go Script.CheckErrorCondition 71.43% (10/14) github.com/conformal/btcscript/script.go isMultiSig 61.54% (8/13) github.com/conformal/btcscript/opcode.go opcodeSha1 60.00% (3/5) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 93.74% (869/927) +github.com/conformal/btcscript -------------------------- 93.84% (869/926) From 53ba8fb83423ef257086abf53f036d29163fd0f3 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Fri, 21 Jun 2013 01:33:56 +0100 Subject: [PATCH 017/174] gofmt --- opcode_test.go | 1328 ++++++++++++++++++++++++------------------------ script.go | 16 +- script_test.go | 53 +- stack_test.go | 12 +- 4 files changed, 704 insertions(+), 705 deletions(-) diff --git a/opcode_test.go b/opcode_test.go index 298292c5..4615019a 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -542,8 +542,8 @@ type detailedTest struct { altafter [][]byte disassembly string disassemblyerr error - nSigOps int // should have same return as disassembly error - nPreciseSigOps int // should have same return as disassembly error + nSigOps int // should have same return as disassembly error + nPreciseSigOps int // should have same return as disassembly error } var detailedTests = []detailedTest{ @@ -2117,7 +2117,7 @@ var detailedTests = []detailedTest{ script: []byte{btcscript.OP_1, btcscript.OP_CHECKSIG}, expectedReturn: btcscript.StackErrUnderflow, disassembly: "OP_1 OP_CHECKSIG", - nSigOps: 1, + nSigOps: 1, nPreciseSigOps: 1, }, { @@ -2125,7 +2125,7 @@ var detailedTests = []detailedTest{ script: []byte{btcscript.OP_CHECKSIG}, expectedReturn: btcscript.StackErrUnderflow, disassembly: "OP_CHECKSIG", - nSigOps: 1, + nSigOps: 1, nPreciseSigOps: 1, }, { @@ -2134,7 +2134,7 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECKSIGVERIFY}, expectedReturn: btcscript.StackErrUnderflow, disassembly: "OP_1 OP_CHECKSIGVERIFY", - nSigOps: 1, + nSigOps: 1, nPreciseSigOps: 1, }, { @@ -2142,7 +2142,7 @@ var detailedTests = []detailedTest{ script: []byte{btcscript.OP_CHECKSIGVERIFY}, expectedReturn: btcscript.StackErrUnderflow, disassembly: "OP_CHECKSIGVERIFY", - nSigOps: 1, + nSigOps: 1, nPreciseSigOps: 1, }, { @@ -2150,7 +2150,7 @@ var detailedTests = []detailedTest{ script: []byte{btcscript.OP_CHECK_MULTISIG}, expectedReturn: btcscript.StackErrUnderflow, disassembly: "OP_CHECK_MULTISIG", - nSigOps: 20, + nSigOps: 20, nPreciseSigOps: 20, }, { @@ -2160,8 +2160,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECK_MULTISIG}, expectedReturn: btcscript.StackErrNumberTooBig, disassembly: "010203040506070809 OP_CHECK_MULTISIG", - nSigOps: 20, - nPreciseSigOps: 20, + nSigOps: 20, + nPreciseSigOps: 20, }, { name: "OP_CHECK_MULTISIG too many keys", @@ -2169,8 +2169,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECK_MULTISIG}, expectedReturn: btcscript.StackErrTooManyPubkeys, disassembly: "15 OP_CHECK_MULTISIG", - nSigOps: 20, - nPreciseSigOps: 20, + nSigOps: 20, + nPreciseSigOps: 20, }, { name: "OP_CHECK_MULTISIG lying about pubkeys", @@ -2178,8 +2178,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECK_MULTISIG}, expectedReturn: btcscript.StackErrUnderflow, disassembly: "OP_1 OP_CHECK_MULTISIG", - nSigOps: 20, - nPreciseSigOps: 1, + nSigOps: 20, + nPreciseSigOps: 1, }, { // pubkey comes from blockchain @@ -2198,8 +2198,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECK_MULTISIG}, expectedReturn: btcscript.StackErrUnderflow, disassembly: "04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECK_MULTISIG", - nSigOps: 20, - nPreciseSigOps: 1, + nSigOps: 20, + nPreciseSigOps: 1, }, { // pubkey comes from blockchain @@ -2220,8 +2220,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECK_MULTISIG}, expectedReturn: btcscript.StackErrNumberTooBig, disassembly: "010203040506070809 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECK_MULTISIG", - nSigOps: 20, - nPreciseSigOps: 1, + nSigOps: 20, + nPreciseSigOps: 1, }, { name: "OP_CHECK_MULTISIG too few sigs", @@ -2239,8 +2239,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECK_MULTISIG}, expectedReturn: btcscript.StackErrUnderflow, disassembly: "OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECK_MULTISIG", - nSigOps: 20, - nPreciseSigOps: 1, + nSigOps: 20, + nPreciseSigOps: 1, }, { // pubkey and sig comes from blockchain, are unrelated @@ -2267,10 +2267,10 @@ var detailedTests = []detailedTest{ 0xd8, 0x4c, btcscript.OP_1, btcscript.OP_CHECK_MULTISIG}, - after: [][]byte{{0}}, - disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECK_MULTISIG", - nSigOps: 20, - nPreciseSigOps: 1, + after: [][]byte{{0}}, + disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECK_MULTISIG", + nSigOps: 20, + nPreciseSigOps: 1, }, { // invalid pubkey means that it fails to validate, not an @@ -2290,10 +2290,10 @@ var detailedTests = []detailedTest{ btcscript.OP_1, btcscript.OP_1, btcscript.OP_1, btcscript.OP_CHECK_MULTISIG}, - after: [][]byte{{0}}, - disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 OP_1 OP_1 OP_CHECK_MULTISIG", - nSigOps: 20, - nPreciseSigOps: 1, + after: [][]byte{{0}}, + disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 OP_1 OP_1 OP_CHECK_MULTISIG", + nSigOps: 20, + nPreciseSigOps: 1, }, // XXX(oga) Test multisig when extra arg is missing. needs valid sig. // disabled opcodes @@ -2302,8 +2302,8 @@ var detailedTests = []detailedTest{ script: []byte{btcscript.OP_CHECKMULTISIGVERIFY}, expectedReturn: btcscript.StackErrUnderflow, disassembly: "OP_CHECKMULTISIGVERIFY", - nSigOps: 20, - nPreciseSigOps: 20, + nSigOps: 20, + nPreciseSigOps: 20, }, { name: "OP_CHECKMULTISIGVERIFY huge number", @@ -2312,8 +2312,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECKMULTISIGVERIFY}, expectedReturn: btcscript.StackErrNumberTooBig, disassembly: "010203040506070809 OP_CHECKMULTISIGVERIFY", - nSigOps: 20, - nPreciseSigOps: 20, + nSigOps: 20, + nPreciseSigOps: 20, }, { name: "OP_CHECKMULTISIGVERIFY too many keys", @@ -2321,8 +2321,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECKMULTISIGVERIFY}, expectedReturn: btcscript.StackErrTooManyPubkeys, disassembly: "15 OP_CHECKMULTISIGVERIFY", - nSigOps: 20, - nPreciseSigOps: 20, + nSigOps: 20, + nPreciseSigOps: 20, }, { name: "OP_CHECKMULTISIGVERIFY lying about pubkeys", @@ -2330,8 +2330,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECKMULTISIGVERIFY}, expectedReturn: btcscript.StackErrUnderflow, disassembly: "OP_1 OP_CHECKMULTISIGVERIFY", - nSigOps: 20, - nPreciseSigOps: 1, + nSigOps: 20, + nPreciseSigOps: 1, }, { // pubkey comes from blockchain @@ -2350,8 +2350,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECKMULTISIGVERIFY}, expectedReturn: btcscript.StackErrUnderflow, disassembly: "04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIGVERIFY", - nSigOps: 20, - nPreciseSigOps: 1, + nSigOps: 20, + nPreciseSigOps: 1, }, { name: "OP_CHECKMULTISIGVERIFY sigs huge no", @@ -2371,8 +2371,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECKMULTISIGVERIFY}, expectedReturn: btcscript.StackErrNumberTooBig, disassembly: "010203040506070809 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIGVERIFY", - nSigOps: 20, - nPreciseSigOps: 1, + nSigOps: 20, + nPreciseSigOps: 1, }, { name: "OP_CHECKMULTISIGVERIFY too few sigs", @@ -2390,8 +2390,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECKMULTISIGVERIFY}, expectedReturn: btcscript.StackErrUnderflow, disassembly: "OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIGVERIFY", - nSigOps: 20, - nPreciseSigOps: 1, + nSigOps: 20, + nPreciseSigOps: 1, }, { // pubkey and sig comes from blockchain, are unrelated @@ -2420,8 +2420,8 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECKMULTISIGVERIFY}, expectedReturn: btcscript.StackErrVerifyFailed, disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIGVERIFY", - nSigOps: 20, - nPreciseSigOps: 1, + nSigOps: 20, + nPreciseSigOps: 1, }, { // invalid pubkey means that it fails to validate, not an @@ -2443,643 +2443,643 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECKMULTISIGVERIFY}, expectedReturn: btcscript.StackErrVerifyFailed, disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 OP_1 OP_1 OP_CHECKMULTISIGVERIFY", - nSigOps: 20, - nPreciseSigOps: 1, + nSigOps: 20, + nPreciseSigOps: 1, }, { // 201 operations + one push, should just fit limits name: "max operations", script: []byte{btcscript.OP_1, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, }, - after: [][]byte{{1}, {1}}, - disassembly: "OP_1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP", + after: [][]byte{{1}, {1}}, + disassembly: "OP_1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP", }, { // 202 operations + one push name: "too many operations", script: []byte{btcscript.OP_1, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, }, expectedReturn: btcscript.StackErrTooManyOperations, - disassembly: "OP_1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP", + disassembly: "OP_1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP", }, { // 202 operations + one push name: "too many operations multisig", script: []byte{btcscript.OP_1, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_1, - btcscript.OP_1, - btcscript.OP_1, - btcscript.OP_1, - btcscript.OP_2, - btcscript.OP_CHECK_MULTISIG, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_DUP, + btcscript.OP_DROP, + btcscript.OP_1, + btcscript.OP_1, + btcscript.OP_1, + btcscript.OP_1, + btcscript.OP_2, + btcscript.OP_CHECK_MULTISIG, }, expectedReturn: btcscript.StackErrTooManyOperations, - disassembly: "OP_1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_1 OP_1 OP_1 OP_1 OP_2 OP_CHECK_MULTISIG", - nSigOps: 20, - nPreciseSigOps: 2, + disassembly: "OP_1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_1 OP_1 OP_1 OP_1 OP_2 OP_CHECK_MULTISIG", + nSigOps: 20, + nPreciseSigOps: 2, }, { name: "OP_CAT disabled", @@ -3802,14 +3802,14 @@ func TestSigOps(t *testing.T) { continue } if test.disassemblyerr != nil { - t.Errorf("%s: no error when expected \"%v\"", + t.Errorf("%s: no error when expected \"%v\"", test.name, test.disassemblyerr) continue } if count != test.nSigOps { t.Errorf("%s: expected count of %d, got %d", test.name, test.nSigOps, count) - + } } } @@ -3834,14 +3834,14 @@ func TestPreciseSigOps(t *testing.T) { continue } if test.disassemblyerr != nil { - t.Errorf("%s: no error when expected \"%v\"", + t.Errorf("%s: no error when expected \"%v\"", test.name, test.disassemblyerr) continue } if count != test.nPreciseSigOps { t.Errorf("%s: expected count of %d, got %d", test.name, test.nPreciseSigOps, count) - + } } } diff --git a/script.go b/script.go index 8fc9e3dc..7cbef226 100644 --- a/script.go +++ b/script.go @@ -718,7 +718,7 @@ func (s *Script) SetAltStack(data [][]byte) { // GetSigOpCount provides a quick count of the number of signature operations // in a script. a CHECKSIG operations counts for 1, and a CHECK_MULTISIG for 20. -func GetSigOpCount(script [] byte) (int, error) { +func GetSigOpCount(script []byte) (int, error) { pops, err := parseScript(script) if err != nil { return 0, err @@ -751,7 +751,7 @@ func GetPreciseSigOpCount(scriptSig, scriptPubKey []byte, bip16 bool) (int, erro return 0, nil } - shScript := sigPops[len(sigPops) - 1].data + shScript := sigPops[len(sigPops)-1].data // Means that sigPops is jus OP_1 - OP_16, no sigops there. if shScript == nil { return 0, nil @@ -774,20 +774,20 @@ func getSigOpCount(pops []parsedOpcode, precise bool) int { for i, pop := range pops { switch pop.opcode.value { case OP_CHECKSIG: - fallthrough; + fallthrough case OP_CHECKSIGVERIFY: nSigs++ case OP_CHECK_MULTISIG: - fallthrough; + fallthrough case OP_CHECKMULTISIGVERIFY: // If we are being precise then look for familiar // patterns for multisig, for now all we recognise is - // OP_1 - OP_16 to signify the number of pubkeys. + // OP_1 - OP_16 to signify the number of pubkeys. // Otherwise, we use the max of 20. if precise && i > 0 && - pops[i - 1].opcode.value >= OP_1 && - pops[i - 1].opcode.value <= OP_16 { - nSigs += int(pops[i-1].opcode.value - + pops[i-1].opcode.value >= OP_1 && + pops[i-1].opcode.value <= OP_16 { + nSigs += int(pops[i-1].opcode.value - (OP_1 - 1)) } else { nSigs += MaxPubKeysPerMultiSig diff --git a/script_test.go b/script_test.go index 69642531..0a4a69f9 100644 --- a/script_test.go +++ b/script_test.go @@ -121,7 +121,7 @@ var txTests = []txTest{ 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, 0xa3, btcscript.OP_CHECKSIG, }, - idx: 0, + idx: 0, nSigOps: 1, }, // Previous test with the value of one output changed. @@ -221,8 +221,8 @@ var txTests = []txTest{ 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, 0xa3, btcscript.OP_CHECKSIG, }, - idx: 0, - err: btcscript.StackErrScriptFailed, + idx: 0, + err: btcscript.StackErrScriptFailed, nSigOps: 1, }, txTest{ @@ -325,7 +325,7 @@ var txTests = []txTest{ }, idx: 0, shouldFail: true, - nSigOps: 1, + nSigOps: 1, }, txTest{ name: "CheckSig invalid pubkey", @@ -426,7 +426,7 @@ var txTests = []txTest{ }, idx: 0, shouldFail: true, - nSigOps: 1, + nSigOps: 1, }, // tx 599e47a8114fe098103663029548811d2651991b62397e057f0c863c2bc9f9ea // uses checksig with SigHashNone. @@ -526,8 +526,8 @@ var txTests = []txTest{ btcscript.OP_EQUALVERIFY, btcscript.OP_CHECKSIG, }, - idx: 0, - bip16: true, // after threshold + idx: 0, + bip16: true, // after threshold nSigOps: 1, }, // tx 51bf528ecf3c161e7c021224197dbe84f9a8564212f6207baa014c01a1668e1e @@ -650,8 +650,8 @@ var txTests = []txTest{ btcscript.OP_EQUALVERIFY, btcscript.OP_CHECKSIG, }, - idx: 0, - bip16: true, // after threshold + idx: 0, + bip16: true, // after threshold nSigOps: 1, }, // tx 6d36bc17e947ce00bb6f12f8e7a56a1585c5a36188ffa2b05e10b4743273a74b @@ -773,8 +773,8 @@ var txTests = []txTest{ 0x4f, 0x13, btcscript.OP_NOP2, btcscript.OP_DROP, }, - idx: 1, - bip16: false, + idx: 1, + bip16: false, nSigOps: 0, // multisig is in the pkScript! }, // same as previous but with one byte changed to make signature fail @@ -895,9 +895,9 @@ var txTests = []txTest{ 0x4f, 0x13, btcscript.OP_NOP2, btcscript.OP_DROP, }, - idx: 1, - bip16: false, - err: btcscript.StackErrScriptFailed, + idx: 1, + bip16: false, + err: btcscript.StackErrScriptFailed, nSigOps: 0, // multisig is in the pkScript! }, // tx e5779b9e78f9650debc2893fd9636d827b26b4ddfa6a8172fe8708c924f5c39d @@ -955,8 +955,8 @@ var txTests = []txTest{ 0xae, 0x88, btcscript.OP_EQUAL, }, - idx: 0, - bip16: true, + idx: 0, + bip16: true, nSigOps: 0, // no signature ops in the pushed script. }, } @@ -1014,7 +1014,7 @@ func TestGetPreciseSignOps(t *testing.T) { if count != test.nSigOps { t.Errorf("%s: expected count of %d, got %d", test.name, test.nSigOps, count) - + } } } @@ -1302,12 +1302,12 @@ func TestBadPC(t *testing.T) { } pcTests := []pcTest{ pcTest{ - script:2, - off:0, + script: 2, + off: 0, }, pcTest{ script: 0, - off: 2, + off: 2, }, } // tx with almost empty scripts. @@ -1329,12 +1329,12 @@ func TestBadPC(t *testing.T) { Index: 0, }, SignatureScript: []uint8{btcscript.OP_NOP}, - Sequence: 4294967295, + Sequence: 4294967295, }, }, TxOut: []*btcwire.TxOut{ &btcwire.TxOut{ - Value: 1000000000, + Value: 1000000000, PkScript: []byte{}, }, }, @@ -1343,7 +1343,7 @@ func TestBadPC(t *testing.T) { pkScript := []byte{btcscript.OP_NOP} for _, test := range pcTests { - engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript, + engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript, pkScript, 0, tx, 70001, false) if err != nil { t.Errorf("Failed to create script: %v", err) @@ -1388,12 +1388,12 @@ func TestCheckErrorCondition(t *testing.T) { Index: 0, }, SignatureScript: []uint8{}, - Sequence: 4294967295, + Sequence: 4294967295, }, }, TxOut: []*btcwire.TxOut{ &btcwire.TxOut{ - Value: 1000000000, + Value: 1000000000, PkScript: []byte{}, }, }, @@ -1419,7 +1419,7 @@ func TestCheckErrorCondition(t *testing.T) { t.Errorf("failed to create script: %v", err) } - for i := 0; i < len(pkScript) - 1; i++ { + for i := 0; i < len(pkScript)-1; i++ { done, err := engine.Step() if err != nil { t.Errorf("failed to step %dth time: %v", i, err) @@ -1452,4 +1452,3 @@ func TestCheckErrorCondition(t *testing.T) { t.Errorf("unexpected error %v on final check", err) } } - diff --git a/stack_test.go b/stack_test.go index 942a227d..f6c6e77c 100644 --- a/stack_test.go +++ b/stack_test.go @@ -235,7 +235,7 @@ var stackTests = []stackTest{ [][]byte{}, }, { - "PushInt 0", + "PushInt 0", [][]byte{}, func(stack *btcscript.Stack) error { stack.PushInt(big.NewInt(0)) @@ -245,7 +245,7 @@ var stackTests = []stackTest{ [][]byte{{}}, }, { - "PushInt 1", + "PushInt 1", [][]byte{}, func(stack *btcscript.Stack) error { stack.PushInt(big.NewInt(1)) @@ -255,7 +255,7 @@ var stackTests = []stackTest{ [][]byte{{0x1}}, }, { - "PushInt -1", + "PushInt -1", [][]byte{}, func(stack *btcscript.Stack) error { stack.PushInt(big.NewInt(-1)) @@ -265,7 +265,7 @@ var stackTests = []stackTest{ [][]byte{{0x81}}, }, { - "PushInt two bytes", + "PushInt two bytes", [][]byte{}, func(stack *btcscript.Stack) error { stack.PushInt(big.NewInt(256)) @@ -276,7 +276,7 @@ var stackTests = []stackTest{ [][]byte{{0x00, 0x01}}, }, { - "PushInt leading zeros", + "PushInt leading zeros", [][]byte{}, func(stack *btcscript.Stack) error { // this will have the highbit set @@ -284,7 +284,7 @@ var stackTests = []stackTest{ return nil }, nil, - [][]byte{{0x80, 0x00 }}, + [][]byte{{0x80, 0x00}}, }, { "dup", From 2bdaebfa740058350727812622766e9cff49ffec Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Mon, 24 Jun 2013 16:32:41 +0100 Subject: [PATCH 018/174] some more tests for GetPreciseSigOpsCount. total coverage now. --- script_test.go | 75 ++++++++++++++++++++++++++++++++++++++++++ test_coverage.txt | 84 +++++++++++++++++++++++------------------------ 2 files changed, 117 insertions(+), 42 deletions(-) diff --git a/script_test.go b/script_test.go index 0a4a69f9..2bb1e059 100644 --- a/script_test.go +++ b/script_test.go @@ -1001,6 +1001,8 @@ func TestTX(t *testing.T) { } func TestGetPreciseSignOps(t *testing.T) { + // First we go over the range of tests in testTx and count the sigops in + // them. for _, test := range txTests { count, err := btcscript.GetPreciseSigOpCount( test.tx.TxIn[test.idx].SignatureScript, test.pkScript, @@ -1017,6 +1019,79 @@ func TestGetPreciseSignOps(t *testing.T) { } } + + // Now we go over a number of tests to hit the more awkward error + // conditions in the P2SH cases.. + + type psocTest struct { + name string + scriptSig []byte + nSigOps int + err error + } + psocTests := []psocTest{ + psocTest{ + name: "scriptSig doesn't parse", + scriptSig: []byte{btcscript.OP_PUSHDATA1, 2}, + err: btcscript.StackErrShortScript, + }, + psocTest{ + name: "scriptSig isn't push only", + scriptSig: []byte{btcscript.OP_1, btcscript.OP_DUP}, + nSigOps: 0, + }, + psocTest{ + name: "scriptSig length 0", + scriptSig: []byte{}, + nSigOps: 0, + }, + psocTest{ + name: "No script at the end", + // No script at end but still push only. + scriptSig: []byte{btcscript.OP_1, btcscript.OP_1}, + nSigOps: 0, + }, + // pushed script doesn't parse. + psocTest{ + name: "pushed script doesn't parse", + scriptSig: []byte{btcscript.OP_DATA_2, + btcscript.OP_PUSHDATA1, 2}, + err: btcscript.StackErrShortScript, + }, + } + // The signature in the p2sh script is nonsensical for the tests since + // this script will never be executed. What matters is that it matches + // the right pattern. + pkScript := []byte{ + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0x43, 0x3e, 0xc2, 0xac, 0x1f, 0xfa, 0x1b, 0x7b, 0x7d, + 0x02, 0x7f, 0x56, 0x45, 0x29, 0xc5, 0x71, 0x97, 0xf9, + 0xae, 0x88, + btcscript.OP_EQUAL, + } + for _, test := range psocTests { + count, err := btcscript.GetPreciseSigOpCount( + test.scriptSig, pkScript, true) + // all tx currently parse + if err != nil { + if err != test.err { + t.Errorf("%s: unexpected error. got \"%v\" exp: \"%v\"", + test.name, err, test.err) + } + continue + } + if test.err != nil { + t.Errorf("%s: expected error \"%v\" got none", + test.name, test.err) + continue + } + if count != test.nSigOps { + t.Errorf("%s: expected count of %d, got %d", test.name, + test.nSigOps, count) + + } + } } type removeOpcodeTest struct { diff --git a/test_coverage.txt b/test_coverage.txt index f3287f46..bdc1efcd 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -1,58 +1,59 @@ github.com/conformal/btcscript/stack.go asInt 100.00% (18/18) +github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (17/17) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) -github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12) github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12) +github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) -github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) -github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) +github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) +github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) -github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) +github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) @@ -64,6 +65,7 @@ github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) github.com/conformal/btcscript/script.go unparseScript 100.00% (4/4) +github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) @@ -74,40 +76,38 @@ github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) -github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) -github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) -github.com/conformal/btcscript/opcode.go init 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) -github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) +github.com/conformal/btcscript/opcode.go init 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) github.com/conformal/btcscript/log.go init 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) @@ -118,8 +118,10 @@ github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.21% (55/56) github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) github.com/conformal/btcscript/address.go ScriptToAddress 94.92% (56/59) @@ -129,14 +131,12 @@ github.com/conformal/btcscript/script.go Script.Step 91.89% (34/37) github.com/conformal/btcscript/script.go typeOfScript 83.33% (5/6) github.com/conformal/btcscript/script.go Script.DisasmScript 80.00% (4/5) github.com/conformal/btcscript/script.go Script.CheckErrorCondition 78.57% (11/14) -github.com/conformal/btcscript/script.go GetPreciseSigOpCount 76.47% (13/17) github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) -github.com/conformal/btcscript/script.go isPushOnly 75.00% (3/4) github.com/conformal/btcscript/script.go Script.calcScriptHash 71.43% (25/35) github.com/conformal/btcscript/script.go isMultiSig 61.54% (8/13) github.com/conformal/btcscript/opcode.go opcodeSha1 60.00% (3/5) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 93.84% (869/926) +github.com/conformal/btcscript -------------------------- 94.38% (874/926) From 4a87e6e3a7ba1b5509103ef7f6961fb0e32adea3 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Tue, 25 Jun 2013 00:12:08 +0100 Subject: [PATCH 019/174] Test a few failure cases of p2sh txs. --- script_test.go | 130 +++++++++++++++++++++++++++++++++++++++++++++- test_coverage.txt | 4 +- 2 files changed, 131 insertions(+), 3 deletions(-) diff --git a/script_test.go b/script_test.go index 2bb1e059..4edfff11 100644 --- a/script_test.go +++ b/script_test.go @@ -20,6 +20,7 @@ type txTest struct { err error shouldFail bool nSigOps int + sigOpsErr error } var txTests = []txTest{ @@ -959,6 +960,126 @@ var txTests = []txTest{ bip16: true, nSigOps: 0, // no signature ops in the pushed script. }, + // next few tests are modified versions of previous to hit p2sh error + // cases. + txTest{ + // sigscript changed so that pkscript hash will not match. + name: "P2SH - bad hash", + tx: &btcwire.MsgTx{ + Version: 1, + TxIn: []*btcwire.TxIn{ + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash([32]byte{ + 0x6d, 0x58, 0xf8, 0xa3, + 0xaa, 0x43, 0x0b, 0x84, + 0x78, 0x52, 0x3a, 0x65, + 0xc2, 0x03, 0xa2, 0x7b, + 0xb8, 0x81, 0x17, 0x8c, + 0xb1, 0x23, 0x13, 0xaf, + 0xde, 0x29, 0xf9, 0x2e, + 0xd7, 0x56, 0xaa, 0x7e, + }), + Index: 0, + }, + SignatureScript: []byte{ + btcscript.OP_DATA_2, + // OP_3 OP_8 + 0x53, 0x58, + }, + Sequence: 4294967295, + }, + }, + TxOut: []*btcwire.TxOut{ + &btcwire.TxOut{ + Value: 1000000, + PkScript: []byte{ + btcscript.OP_DUP, + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0x5b, 0x69, 0xd8, 0xb9, 0xdf, + 0xa6, 0xe4, 0x12, 0x26, 0x47, + 0xe1, 0x79, 0x4e, 0xaa, 0x3b, + 0xfc, 0x11, 0x1f, 0x70, 0xef, + btcscript.OP_EQUALVERIFY, + btcscript.OP_CHECKSIG, + }, + }, + }, + LockTime: 0, + }, + pkScript: []byte{ + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0x43, 0x3e, 0xc2, 0xac, 0x1f, 0xfa, 0x1b, 0x7b, 0x7d, + 0x02, 0x7f, 0x56, 0x45, 0x29, 0xc5, 0x71, 0x97, 0xf9, + 0xae, 0x88, + btcscript.OP_EQUAL, + }, + idx: 0, + err: btcscript.StackErrScriptFailed, + bip16: true, + nSigOps: 0, // no signature ops in the pushed script. + }, + txTest{ + // sigscript changed so that pkscript hash will not match. + name: "P2SH - doesn't parse", + tx: &btcwire.MsgTx{ + Version: 1, + TxIn: []*btcwire.TxIn{ + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash([32]byte{ + 0x6d, 0x58, 0xf8, 0xa3, + 0xaa, 0x43, 0x0b, 0x84, + 0x78, 0x52, 0x3a, 0x65, + 0xc2, 0x03, 0xa2, 0x7b, + 0xb8, 0x81, 0x17, 0x8c, + 0xb1, 0x23, 0x13, 0xaf, + 0xde, 0x29, 0xf9, 0x2e, + 0xd7, 0x56, 0xaa, 0x7e, + }), + Index: 0, + }, + SignatureScript: []byte{ + btcscript.OP_DATA_2, + // pushed script. + btcscript.OP_DATA_2, 0x1, + }, + Sequence: 4294967295, + }, + }, + TxOut: []*btcwire.TxOut{ + &btcwire.TxOut{ + Value: 1000000, + PkScript: []byte{ + btcscript.OP_DUP, + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0x5b, 0x69, 0xd8, 0xb9, 0xdf, + 0xa6, 0xe4, 0x12, 0x26, 0x47, + 0xe1, 0x79, 0x4e, 0xaa, 0x3b, + 0xfc, 0x11, 0x1f, 0x70, 0xef, + btcscript.OP_EQUALVERIFY, + btcscript.OP_CHECKSIG, + }, + }, + }, + LockTime: 0, + }, + pkScript: []byte{ + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0xd4, 0x8c, 0xe8, 0x6c, 0x69, 0x8f, 0x24, 0x68, 0x29, + 0x92, 0x1b, 0xa9, 0xfb, 0x2a, 0x84, 0x4a, 0xe2, 0xad, + 0xba, 0x67, + btcscript.OP_EQUAL, + }, + idx: 0, + err: btcscript.StackErrShortScript, + bip16: true, + sigOpsErr: btcscript.StackErrShortScript, + }, } // Test a number of tx from the blockchain to test otherwise difficult to test @@ -1009,7 +1130,14 @@ func TestGetPreciseSignOps(t *testing.T) { test.bip16) // all tx currently parse if err != nil { - t.Errorf("%s: unexpected error. got \"%v\"", + if err != test.sigOpsErr { + t.Errorf("%s: unexpected error. got \"%v\"", + test.name, err) + } + continue + } + if test.sigOpsErr != nil { + t.Errorf("%s: expected error \"%v\" but got success", test.name, err) continue } diff --git a/test_coverage.txt b/test_coverage.txt index bdc1efcd..72c84a56 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -123,11 +123,11 @@ github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.21% (55/56) +github.com/conformal/btcscript/script.go Script.Step 97.30% (36/37) github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) github.com/conformal/btcscript/address.go ScriptToAddress 94.92% (56/59) github.com/conformal/btcscript/script.go NewScript 94.74% (18/19) github.com/conformal/btcscript/script.go parseScript 93.75% (30/32) -github.com/conformal/btcscript/script.go Script.Step 91.89% (34/37) github.com/conformal/btcscript/script.go typeOfScript 83.33% (5/6) github.com/conformal/btcscript/script.go Script.DisasmScript 80.00% (4/5) github.com/conformal/btcscript/script.go Script.CheckErrorCondition 78.57% (11/14) @@ -138,5 +138,5 @@ github.com/conformal/btcscript/opcode.go opcodeSha1 60.00% (3/5) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 94.38% (874/926) +github.com/conformal/btcscript -------------------------- 94.60% (876/926) From 7e937fae7540f3966b641a06659f857114ada70d Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Tue, 25 Jun 2013 13:12:15 +0100 Subject: [PATCH 020/174] testing for the case where a p2sh sigscript isn't pushonly. Also providing a defined error (from NewScript) for that case. --- script.go | 9 +++- script_test.go | 117 +++++++++++++++++++++++++++++++++++++--------- test_coverage.txt | 90 +++++++++++++++++------------------ 3 files changed, 146 insertions(+), 70 deletions(-) diff --git a/script.go b/script.go index 7cbef226..8540812c 100644 --- a/script.go +++ b/script.go @@ -86,6 +86,12 @@ var StackErrScriptUnfinished = errors.New("Error check when script unfinished") // when the scripts have finished executing. var StackErrEmptyStack = errors.New("Stack empty at end of execution") +// StackErrP2SHNonPushOnly is returned when a Pay-to-Script-Hash transaction +// is encountered and the ScriptSig does operations other than push data (in +// violation of bip16). +var StackErrP2SHNonPushOnly = errors.New("pay to script hash with non " + + "pushonly input") + // Bip16Activation is the timestamp where BIP0016 is valid to use in the // blockchain. To be used to determine if BIP0016 should be called for or not. // This timestamp corresponds to Sun Apr 1 00:00:00 UTC 2012. @@ -319,8 +325,7 @@ func NewScript(scriptSig []byte, scriptPubKey []byte, txidx int, tx *btcwire.Msg // if we are pay to scripthash then we only accept input // scripts that push data if !isPushOnly(m.scripts[0]) { - return nil, errors.New("pay to script hash with non " + - "pushonly input") + return nil, StackErrP2SHNonPushOnly } m.bip16 = true } diff --git a/script_test.go b/script_test.go index 4edfff11..00df549e 100644 --- a/script_test.go +++ b/script_test.go @@ -15,12 +15,13 @@ type txTest struct { name string tx *btcwire.MsgTx pkScript []byte // output script of previous tx - idx int - bip16 bool - err error - shouldFail bool - nSigOps int - sigOpsErr error + idx int // tx idx to be run. + bip16 bool // is bip16 active? + parseErr error // failure of NewScript + err error // Failure of Executre + shouldFail bool // Execute should fail with nonspecified error. + nSigOps int // result of GetPreciseSigOpsCount + sigOpsErr error // failure of GetPreciseSigOpsCount() } var txTests = []txTest{ @@ -1072,14 +1073,77 @@ var txTests = []txTest{ btcscript.OP_DATA_20, 0xd4, 0x8c, 0xe8, 0x6c, 0x69, 0x8f, 0x24, 0x68, 0x29, 0x92, 0x1b, 0xa9, 0xfb, 0x2a, 0x84, 0x4a, 0xe2, 0xad, - 0xba, 0x67, + 0xba, 0x67, btcscript.OP_EQUAL, }, - idx: 0, - err: btcscript.StackErrShortScript, - bip16: true, + idx: 0, + err: btcscript.StackErrShortScript, + bip16: true, sigOpsErr: btcscript.StackErrShortScript, }, + txTest{ + // sigscript changed so to be non pushonly. + name: "P2SH - non pushonly", + tx: &btcwire.MsgTx{ + Version: 1, + TxIn: []*btcwire.TxIn{ + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash([32]byte{ + 0x6d, 0x58, 0xf8, 0xa3, + 0xaa, 0x43, 0x0b, 0x84, + 0x78, 0x52, 0x3a, 0x65, + 0xc2, 0x03, 0xa2, 0x7b, + 0xb8, 0x81, 0x17, 0x8c, + 0xb1, 0x23, 0x13, 0xaf, + 0xde, 0x29, 0xf9, 0x2e, + 0xd7, 0x56, 0xaa, 0x7e, + }), + Index: 0, + }, + // doesn't have to match signature. + // will never run. + SignatureScript: []byte{ + + btcscript.OP_DATA_2, + // pushed script. + btcscript.OP_DATA_1, 0x1, + btcscript.OP_DUP, + }, + Sequence: 4294967295, + }, + }, + TxOut: []*btcwire.TxOut{ + &btcwire.TxOut{ + Value: 1000000, + PkScript: []byte{ + btcscript.OP_DUP, + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0x5b, 0x69, 0xd8, 0xb9, 0xdf, + 0xa6, 0xe4, 0x12, 0x26, 0x47, + 0xe1, 0x79, 0x4e, 0xaa, 0x3b, + 0xfc, 0x11, 0x1f, 0x70, 0xef, + btcscript.OP_EQUALVERIFY, + btcscript.OP_CHECKSIG, + }, + }, + }, + LockTime: 0, + }, + pkScript: []byte{ + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0x43, 0x3e, 0xc2, 0xac, 0x1f, 0xfa, 0x1b, 0x7b, 0x7d, + 0x02, 0x7f, 0x56, 0x45, 0x29, 0xc5, 0x71, 0x97, 0xf9, + 0xae, 0x88, + btcscript.OP_EQUAL, + }, + idx: 0, + parseErr: btcscript.StackErrP2SHNonPushOnly, + bip16: true, + nSigOps: 0, // no signature ops in the pushed script. + }, } // Test a number of tx from the blockchain to test otherwise difficult to test @@ -1093,9 +1157,16 @@ func testTx(t *testing.T, test txTest) { test.tx.TxIn[test.idx].SignatureScript, test.pkScript, test.idx, test.tx, 70001, test.bip16) if err != nil { - t.Errorf("Failed to parse %s: %v", test.name, err) + if err != test.parseErr { + t.Errorf("Failed to parse %s: got \"%v\" expected "+ + "\"%v\"", test.name, err, test.parseErr) + } return } + if test.parseErr != nil { + t.Errorf("%s: parse succeeded when expecting \"%v\"", test.name, + test.parseErr) + } err = engine.Execute() if err != nil { @@ -1152,32 +1223,32 @@ func TestGetPreciseSignOps(t *testing.T) { // conditions in the P2SH cases.. type psocTest struct { - name string + name string scriptSig []byte - nSigOps int - err error + nSigOps int + err error } psocTests := []psocTest{ psocTest{ - name: "scriptSig doesn't parse", + name: "scriptSig doesn't parse", scriptSig: []byte{btcscript.OP_PUSHDATA1, 2}, - err: btcscript.StackErrShortScript, + err: btcscript.StackErrShortScript, }, psocTest{ - name: "scriptSig isn't push only", + name: "scriptSig isn't push only", scriptSig: []byte{btcscript.OP_1, btcscript.OP_DUP}, - nSigOps: 0, + nSigOps: 0, }, psocTest{ - name: "scriptSig length 0", + name: "scriptSig length 0", scriptSig: []byte{}, - nSigOps: 0, + nSigOps: 0, }, psocTest{ name: "No script at the end", // No script at end but still push only. scriptSig: []byte{btcscript.OP_1, btcscript.OP_1}, - nSigOps: 0, + nSigOps: 0, }, // pushed script doesn't parse. psocTest{ @@ -1204,8 +1275,8 @@ func TestGetPreciseSignOps(t *testing.T) { // all tx currently parse if err != nil { if err != test.err { - t.Errorf("%s: unexpected error. got \"%v\" exp: \"%v\"", - test.name, err, test.err) + t.Errorf("%s: unexpected error. got \"%v\" exp: \"%v\"", + test.name, err, test.err) } continue } diff --git a/test_coverage.txt b/test_coverage.txt index 72c84a56..15e53197 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -1,59 +1,60 @@ +github.com/conformal/btcscript/script.go NewScript 100.00% (19/19) github.com/conformal/btcscript/stack.go asInt 100.00% (18/18) github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (17/17) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) +github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12) -github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) +github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) -github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) -github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) +github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) -github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) +github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) +github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) -github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) @@ -76,34 +77,25 @@ github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) -github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) -github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) -github.com/conformal/btcscript/opcode.go init 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) -github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) github.com/conformal/btcscript/log.go init 100.00% (1/1) github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) @@ -117,16 +109,24 @@ github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) +github.com/conformal/btcscript/opcode.go init 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) +github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) +github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.21% (55/56) github.com/conformal/btcscript/script.go Script.Step 97.30% (36/37) github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) github.com/conformal/btcscript/address.go ScriptToAddress 94.92% (56/59) -github.com/conformal/btcscript/script.go NewScript 94.74% (18/19) github.com/conformal/btcscript/script.go parseScript 93.75% (30/32) github.com/conformal/btcscript/script.go typeOfScript 83.33% (5/6) github.com/conformal/btcscript/script.go Script.DisasmScript 80.00% (4/5) @@ -138,5 +138,5 @@ github.com/conformal/btcscript/opcode.go opcodeSha1 60.00% (3/5) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 94.60% (876/926) +github.com/conformal/btcscript -------------------------- 94.71% (877/926) From 7ae307abfd309d4ea1aa592c232843aa218b21a0 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Wed, 26 Jun 2013 14:16:00 +0100 Subject: [PATCH 021/174] Fix case where we have an empty script that isn't the first. Silly check needed to confirm it was the first script. Add test for this case. --- script.go | 8 ++-- script_test.go | 51 +++++++++++++++++++++++ test_coverage.txt | 104 +++++++++++++++++++++++----------------------- 3 files changed, 108 insertions(+), 55 deletions(-) diff --git a/script.go b/script.go index 8540812c..e3a7bfc9 100644 --- a/script.go +++ b/script.go @@ -314,9 +314,11 @@ func NewScript(scriptSig []byte, scriptPubKey []byte, txidx int, tx *btcwire.Msg return nil, err } - // if the first scripts(s) are empty, must set the PC to the next script. - if len(scr) == 0 { - // yes this could end up setting to an invalid intial PC if all scripts were empty + // If the first scripts(s) are empty, must start on later ones. + if i == 0 && len(scr) == 0 { + // This could end up seeing an invalid initial pc if + // all scripts were empty. However, that is an invalid + // case and should fail. m.scriptidx = i + 1 } } diff --git a/script_test.go b/script_test.go index 00df549e..04996923 100644 --- a/script_test.go +++ b/script_test.go @@ -1144,6 +1144,57 @@ var txTests = []txTest{ bip16: true, nSigOps: 0, // no signature ops in the pushed script. }, + txTest{ + // sigscript changed so to be non pushonly. + name: "empty pkScript", + tx: &btcwire.MsgTx{ + Version: 1, + TxIn: []*btcwire.TxIn{ + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash([32]byte{ + 0x6d, 0x58, 0xf8, 0xa3, + 0xaa, 0x43, 0x0b, 0x84, + 0x78, 0x52, 0x3a, 0x65, + 0xc2, 0x03, 0xa2, 0x7b, + 0xb8, 0x81, 0x17, 0x8c, + 0xb1, 0x23, 0x13, 0xaf, + 0xde, 0x29, 0xf9, 0x2e, + 0xd7, 0x56, 0xaa, 0x7e, + }), + Index: 0, + }, + // doesn't have to match signature. + // will never run. + SignatureScript: []byte{ + btcscript.OP_TRUE, + }, + Sequence: 4294967295, + }, + }, + TxOut: []*btcwire.TxOut{ + &btcwire.TxOut{ + Value: 1000000, + PkScript: []byte{ + btcscript.OP_DUP, + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0x5b, 0x69, 0xd8, 0xb9, 0xdf, + 0xa6, 0xe4, 0x12, 0x26, 0x47, + 0xe1, 0x79, 0x4e, 0xaa, 0x3b, + 0xfc, 0x11, 0x1f, 0x70, 0xef, + btcscript.OP_EQUALVERIFY, + btcscript.OP_CHECKSIG, + }, + }, + }, + LockTime: 0, + }, + pkScript: []byte{}, + idx: 0, + bip16: true, + nSigOps: 0, // no signature ops in the pushed script. + }, } // Test a number of tx from the blockchain to test otherwise difficult to test diff --git a/test_coverage.txt b/test_coverage.txt index 15e53197..0b424aca 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -1,60 +1,61 @@ +github.com/conformal/btcscript/script.go Script.Step 100.00% (37/37) github.com/conformal/btcscript/script.go NewScript 100.00% (19/19) github.com/conformal/btcscript/stack.go asInt 100.00% (18/18) github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (17/17) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) -github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12) +github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) -github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) +github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) +github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) -github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) +github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) @@ -71,60 +72,59 @@ github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (4/4) -github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) -github.com/conformal/btcscript/script.go setStack 100.00% (3/3) -github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) +github.com/conformal/btcscript/script.go setStack 100.00% (3/3) +github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) -github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) -github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) -github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) -github.com/conformal/btcscript/log.go init 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) -github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) -github.com/conformal/btcscript/opcode.go init 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go init 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) +github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) +github.com/conformal/btcscript/log.go init 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.21% (55/56) -github.com/conformal/btcscript/script.go Script.Step 97.30% (36/37) github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) github.com/conformal/btcscript/address.go ScriptToAddress 94.92% (56/59) github.com/conformal/btcscript/script.go parseScript 93.75% (30/32) @@ -138,5 +138,5 @@ github.com/conformal/btcscript/opcode.go opcodeSha1 60.00% (3/5) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 94.71% (877/926) +github.com/conformal/btcscript -------------------------- 94.82% (878/926) From d6161f0d4136eaaac7fb17eb9ed6c958d6afbfdb Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Wed, 26 Jun 2013 22:11:54 +0100 Subject: [PATCH 022/174] fix ScriptToAddress when called with 0 length script. It did work by luck before, but now it works no matter what the template tables say. Add tests for the other error cases and internal data assertions. --- address.go | 42 ++++++++++++------------ address_test.go | 3 ++ internal_test.go | 67 ++++++++++++++++++++++++++++++++++++++ script.go | 8 +++++ test_coverage.txt | 83 ++++++++++++++++++++++++----------------------- 5 files changed, 142 insertions(+), 61 deletions(-) diff --git a/address.go b/address.go index 02eacc8a..7c652abf 100644 --- a/address.go +++ b/address.go @@ -91,7 +91,10 @@ func ScriptToAddress(script []byte) (ScriptType, string, error) { {ScriptStrange, scrNoAddr, 33, []pkbytes{{0, OP_DATA_32}}, false}, {ScriptStrange, scrNoAddr, 33, []pkbytes{{0, OP_HASH160}, {1, OP_DATA_20}, {22, OP_EQUAL}}, false}, } + return scriptToAddressTemplate(script, validformats) +} +func scriptToAddressTemplate(script []byte, validformats []pkformat) (ScriptType, string, error) { var format pkformat var success bool for _, format = range validformats { @@ -106,8 +109,8 @@ func ScriptToAddress(script []byte) (ScriptType, string, error) { success = true for _, pkbyte := range format.databytes { if pkbyte.off >= len(script) { - success = false - break + return ScriptUnknown, "Unknown", + StackErrInvalidAddrOffset } if script[pkbyte.off] != pkbyte.val { log.Tracef("off at byte %v %v %v", pkbyte.off, script[pkbyte.off], pkbyte.val) @@ -122,23 +125,22 @@ func ScriptToAddress(script []byte) (ScriptType, string, error) { } } - if success == false && len(script) > 1 { - // check for a few special case - if script[len(script)-1] == OP_CHECK_MULTISIG { - // Multisig ScriptPubKey - return ScriptStrange, "Unknown", nil - } - if script[0] == OP_0 && (len(script) <= 75 && byte(len(script)) == script[1]+2) { - // Multisig ScriptSig - return ScriptStrange, "Unknown", nil - } - if script[0] == OP_HASH160 && len(script) == 23 && script[22] == OP_EQUAL { - // Multisig ScriptSig - return ScriptStrange, "Unknown", nil - } - if script[0] == OP_DATA_36 && len(script) == 37 { - // Multisig ScriptSig - return ScriptStrange, "Unknown", nil + if success == false { + if len(script) > 1 { + // check for a few special case + if script[len(script)-1] == OP_CHECK_MULTISIG { + return ScriptStrange, "Unknown", nil + } + if script[0] == OP_0 && (len(script) <= 75 && byte(len(script)) == script[1]+2) { + return ScriptStrange, "Unknown", nil + } + if script[0] == OP_HASH160 && len(script) == 23 && script[22] == OP_EQUAL { + return ScriptStrange, "Unknown", nil + } + if script[0] == OP_DATA_36 && len(script) == 37 { + // Multisig ScriptSig + return ScriptStrange, "Unknown", nil + } } return ScriptUnknown, "Unknown", StackErrUnknownAddress @@ -175,7 +177,7 @@ func ScriptToAddress(script []byte) (ScriptType, string, error) { pubkey := script[1:34] abuf = calcHash160(pubkey) default: - log.Warnf("parsetype is %v", format.parsetype) + return ScriptUnknown, "Unknown", StackErrInvalidParseType } if abuf != nil { diff --git a/address_test.go b/address_test.go index d1f3f96a..a969dd60 100644 --- a/address_test.go +++ b/address_test.go @@ -170,6 +170,9 @@ var addressTests = []addressTest{ address: "Unknown", class: btcscript.ScriptStrange, }, + {script: []byte{}, + shouldFail: btcscript.StackErrUnknownAddress, + }, } func TestAddresses(t *testing.T) { diff --git a/internal_test.go b/internal_test.go index 239456df..9e282c66 100644 --- a/internal_test.go +++ b/internal_test.go @@ -4,6 +4,10 @@ package btcscript +import ( + "testing" +) + // this file is present to export some internal interfaces so that we can // test them reliably. @@ -49,3 +53,66 @@ func (s *Script) TstSetPC(script, off int) { s.scriptidx = script s.scriptoff = off } + +// Tests for internal error cases in ScriptToAddress. +// We pass bad format definitions to ScriptToAddrss to make sure the internal +// checks work correctly. This is located in internal_test.go and not address.go +// because of the ridiculous amount of internal types/constants that would +// otherwise need to be exported here. + +type pkformatTest struct { + name string + format pkformat + script []byte + ty ScriptType + err error +} + +var TstPkFormats = []pkformatTest{ + pkformatTest{ + name: "bad offset", + format: pkformat{ + addrtype: ScriptAddr, + parsetype: scrNoAddr, + length: 4, + databytes: []pkbytes{{0, OP_1}, {1, OP_2}, {2, + OP_3}, /* wrong - too long */ {9, OP_4}}, + allowmore: true, + }, + script: []byte{OP_1, OP_2, OP_3, OP_4}, + err: StackErrInvalidAddrOffset, + }, + pkformatTest{ + name: "Bad parsetype", + format: pkformat{ + addrtype: ScriptAddr, + parsetype: 8, // invalid type + length: 4, + databytes: []pkbytes{{0, OP_1}, {1, OP_2}, {2, + OP_3}, /* wrong - too long */ {3, OP_4}}, + allowmore: true, + }, + script: []byte{OP_1, OP_2, OP_3, OP_4}, + err: StackErrInvalidParseType, + }, +} + +func TestBadPkFormat(t *testing.T) { + for _, test := range TstPkFormats { + ty, addr, err := scriptToAddressTemplate(test.script, + []pkformat{test.format}) + if err != nil { + if err != test.err { + t.Errorf("%s got error \"%v\". Was expecrting "+ + "\"%v\"", test.name, err, test.err) + } + continue + } + if ty != test.ty { + t.Errorf("%s: unexpected type \"%s\". Wanted \"%s\" (addr %v)", + test.name, ty, test.ty, addr) + continue + } + } + +} diff --git a/script.go b/script.go index e3a7bfc9..11b64aa0 100644 --- a/script.go +++ b/script.go @@ -92,6 +92,14 @@ var StackErrEmptyStack = errors.New("Stack empty at end of execution") var StackErrP2SHNonPushOnly = errors.New("pay to script hash with non " + "pushonly input") +// StackErrInvalidParseType is an internal error returned from ScriptToAddress +// ony if the internal data tables are wrong. +var StackErrInvalidParseType = errors.New("internal error: invalid parsetype found") + +// StackErrInvalidAddrOffset is an internal error returned from ScriptToAddress +// ony if the internal data tables are wrong. +var StackErrInvalidAddrOffset = errors.New("internal error: invalid offset found") + // Bip16Activation is the timestamp where BIP0016 is valid to use in the // blockchain. To be used to determine if BIP0016 should be called for or not. // This timestamp corresponds to Sun Apr 1 00:00:00 UTC 2012. diff --git a/test_coverage.txt b/test_coverage.txt index 0b424aca..8e57caa9 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -1,61 +1,62 @@ +github.com/conformal/btcscript/address.go scriptToAddressTemplate 100.00% (58/58) github.com/conformal/btcscript/script.go Script.Step 100.00% (37/37) github.com/conformal/btcscript/script.go NewScript 100.00% (19/19) github.com/conformal/btcscript/stack.go asInt 100.00% (18/18) github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (17/17) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) -github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) -github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12) github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12) -github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) +github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12) +github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) -github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) +github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) +github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) @@ -72,22 +73,22 @@ github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (4/4) -github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) -github.com/conformal/btcscript/script.go setStack 100.00% (3/3) -github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) +github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) +github.com/conformal/btcscript/script.go setStack 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) +github.com/conformal/btcscript/address.go ScriptToAddress 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) github.com/conformal/btcscript/opcode.go init 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) @@ -99,7 +100,7 @@ github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) @@ -107,14 +108,14 @@ github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) @@ -124,9 +125,9 @@ github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) github.com/conformal/btcscript/log.go init 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.21% (55/56) github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) -github.com/conformal/btcscript/address.go ScriptToAddress 94.92% (56/59) github.com/conformal/btcscript/script.go parseScript 93.75% (30/32) github.com/conformal/btcscript/script.go typeOfScript 83.33% (5/6) github.com/conformal/btcscript/script.go Script.DisasmScript 80.00% (4/5) @@ -138,5 +139,5 @@ github.com/conformal/btcscript/opcode.go opcodeSha1 60.00% (3/5) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 94.82% (878/926) +github.com/conformal/btcscript -------------------------- 95.15% (882/927) From df898ae1dd7ec7a523f33491166b94c8e4993d33 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Wed, 26 Jun 2013 23:28:44 +0100 Subject: [PATCH 023/174] test a few non-standards script types to hit some edge cases. --- script_test.go | 72 +++++++++++++++++++++++++++ test_coverage.txt | 124 +++++++++++++++++++++++----------------------- 2 files changed, 134 insertions(+), 62 deletions(-) diff --git a/script_test.go b/script_test.go index 04996923..67671d19 100644 --- a/script_test.go +++ b/script_test.go @@ -1603,6 +1603,78 @@ var scriptTypeTests = []scriptTypeTest{ }, scripttype: btcscript.TstScriptHashTy, }, + // The next few are almost multisig (it is the more complex script type) + // but with various changes to make it fail. + scriptTypeTest{ + // multisig but funny nsigs.. + name: "strange 1", + script: []byte{ + btcscript.OP_DUP, + btcscript.OP_DATA_33, + 0x02, 0x32, 0xab, 0xdc, 0x89, 0x3e, 0x7f, 0x06, 0x31, + 0x36, 0x4d, 0x7f, 0xd0, 0x1c, 0xb3, 0x3d, 0x24, 0xda, + 0x45, 0x32, 0x9a, 0x00, 0x35, 0x7b, 0x3a, 0x78, 0x86, + 0x21, 0x1a, 0xb4, 0x14, 0xd5, 0x5a, + btcscript.OP_TRUE, + btcscript.OP_CHECK_MULTISIG, + }, + scripttype: btcscript.TstNonStandardTy, + }, + scriptTypeTest{ + name: "strange 2", + // multisig but funny pubkey. + script: []byte{ + btcscript.OP_TRUE, + btcscript.OP_TRUE, + btcscript.OP_TRUE, + btcscript.OP_CHECK_MULTISIG, + }, + scripttype: btcscript.TstNonStandardTy, + }, + scriptTypeTest{ + name: "strange 3", + // multisig but no matching npubkeys opcode. + script: []byte{ + btcscript.OP_TRUE, + btcscript.OP_DATA_33, + 0x02, 0x32, 0xab, 0xdc, 0x89, 0x3e, 0x7f, 0x06, 0x31, + 0x36, 0x4d, 0x7f, 0xd0, 0x1c, 0xb3, 0x3d, 0x24, 0xda, + 0x45, 0x32, 0x9a, 0x00, 0x35, 0x7b, 0x3a, 0x78, 0x86, + 0x21, 0x1a, 0xb4, 0x14, 0xd5, 0x5a, + btcscript.OP_DATA_33, + 0x02, 0x32, 0xab, 0xdc, 0x89, 0x3e, 0x7f, 0x06, 0x31, + 0x36, 0x4d, 0x7f, 0xd0, 0x1c, 0xb3, 0x3d, 0x24, 0xda, + 0x45, 0x32, 0x9a, 0x00, 0x35, 0x7b, 0x3a, 0x78, 0x86, + 0x21, 0x1a, 0xb4, 0x14, 0xd5, 0x5a, + // No number. + btcscript.OP_CHECK_MULTISIG, + }, + scripttype: btcscript.TstNonStandardTy, + }, + scriptTypeTest{ + name: "strange 4", + // multisig but with multisigverify + script: []byte{ + btcscript.OP_TRUE, + btcscript.OP_DATA_33, + 0x02, 0x32, 0xab, 0xdc, 0x89, 0x3e, 0x7f, 0x06, 0x31, + 0x36, 0x4d, 0x7f, 0xd0, 0x1c, 0xb3, 0x3d, 0x24, 0xda, + 0x45, 0x32, 0x9a, 0x00, 0x35, 0x7b, 0x3a, 0x78, 0x86, + 0x21, 0x1a, 0xb4, 0x14, 0xd5, 0x5a, + btcscript.OP_TRUE, + btcscript.OP_CHECKMULTISIGVERIFY, + }, + scripttype: btcscript.TstNonStandardTy, + }, + scriptTypeTest{ + name: "strange 5", + // multisig but wrong length. + script: []byte{ + btcscript.OP_TRUE, + btcscript.OP_CHECK_MULTISIG, + }, + scripttype: btcscript.TstNonStandardTy, + }, } func testScriptType(t *testing.T, test *scriptTypeTest) { diff --git a/test_coverage.txt b/test_coverage.txt index 8e57caa9..d5cb8898 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -5,58 +5,60 @@ github.com/conformal/btcscript/script.go NewScript 100.00% (19/19) github.com/conformal/btcscript/stack.go asInt 100.00% (18/18) github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (17/17) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) +github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) -github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12) github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12) +github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) +github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) -github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) +github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) +github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) -github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) +github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) -github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) +github.com/conformal/btcscript/script.go typeOfScript 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) @@ -73,71 +75,69 @@ github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (4/4) -github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) -github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) -github.com/conformal/btcscript/script.go setStack 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) -github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) +github.com/conformal/btcscript/script.go setStack 100.00% (3/3) +github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) github.com/conformal/btcscript/address.go ScriptToAddress 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) -github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go init 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) -github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) -github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) -github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) +github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) +github.com/conformal/btcscript/opcode.go init 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) +github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) +github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) github.com/conformal/btcscript/log.go init 100.00% (1/1) github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.21% (55/56) github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) github.com/conformal/btcscript/script.go parseScript 93.75% (30/32) -github.com/conformal/btcscript/script.go typeOfScript 83.33% (5/6) github.com/conformal/btcscript/script.go Script.DisasmScript 80.00% (4/5) github.com/conformal/btcscript/script.go Script.CheckErrorCondition 78.57% (11/14) github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) github.com/conformal/btcscript/script.go Script.calcScriptHash 71.43% (25/35) -github.com/conformal/btcscript/script.go isMultiSig 61.54% (8/13) github.com/conformal/btcscript/opcode.go opcodeSha1 60.00% (3/5) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 95.15% (882/927) +github.com/conformal/btcscript -------------------------- 95.79% (888/927) From dd216cef29313a8fe77ee20367915d1dc866eee4 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Wed, 26 Jun 2013 23:57:49 +0100 Subject: [PATCH 024/174] Test pushing at and beyond the boundary for largest stack item. --- opcode_test.go | 190 ++++++++++++++++++++++++++++++++++++++++++++++ test_coverage.txt | 4 +- 2 files changed, 192 insertions(+), 2 deletions(-) diff --git a/opcode_test.go b/opcode_test.go index 4615019a..e355a67f 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -3081,6 +3081,196 @@ var detailedTests = []detailedTest{ nSigOps: 20, nPreciseSigOps: 2, }, + { + name: "push largest", + // 521 bytes + before: [][]byte{}, + script: []byte{btcscript.OP_PUSHDATA2, 0x08, 0x02, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,}, + after: [][]byte{{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,}}, + disassembly: "01020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607", + }, + { + name: "push too large", + // 521 bytes + script: []byte{btcscript.OP_PUSHDATA2, 0x09, 0x02, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,}, + expectedReturn: btcscript.StackErrElementTooBig, + // element too big is a parse error. + disassemblyerr: btcscript.StackErrElementTooBig, + }, { name: "OP_CAT disabled", script: []byte{btcscript.OP_CAT}, diff --git a/test_coverage.txt b/test_coverage.txt index d5cb8898..aff80910 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -129,8 +129,8 @@ github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) github.com/conformal/btcscript/log.go init 100.00% (1/1) github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.21% (55/56) +github.com/conformal/btcscript/script.go parseScript 96.88% (31/32) github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) -github.com/conformal/btcscript/script.go parseScript 93.75% (30/32) github.com/conformal/btcscript/script.go Script.DisasmScript 80.00% (4/5) github.com/conformal/btcscript/script.go Script.CheckErrorCondition 78.57% (11/14) github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) @@ -139,5 +139,5 @@ github.com/conformal/btcscript/opcode.go opcodeSha1 60.00% (3/5) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 95.79% (888/927) +github.com/conformal/btcscript -------------------------- 95.90% (889/927) From bcd8c9d2276d5640a3ca14c485e0bdf01e6e2222 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Thu, 27 Jun 2013 14:19:43 +0100 Subject: [PATCH 025/174] gofmt --- opcode_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/opcode_test.go b/opcode_test.go index e355a67f..a23448b6 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -3143,8 +3143,8 @@ var detailedTests = []detailedTest{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,}, - after: [][]byte{{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}, + after: [][]byte{{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, @@ -3202,8 +3202,8 @@ var detailedTests = []detailedTest{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,}}, - disassembly: "01020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607", + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}}, + disassembly: "01020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607080901020304050607", }, { name: "push too large", @@ -3266,7 +3266,7 @@ var detailedTests = []detailedTest{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,}, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, expectedReturn: btcscript.StackErrElementTooBig, // element too big is a parse error. disassemblyerr: btcscript.StackErrElementTooBig, From 244ce4b96ede62b330aaf7fddb852dc7f2801519 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Thu, 27 Jun 2013 00:32:11 +0100 Subject: [PATCH 026/174] add IsPayToScriptHash api To tell ifa bytestream matches teh p2sh pattern. --- script.go | 10 +++ script_test.go | 18 ++++++ test_coverage.txt | 151 +++++++++++++++++++++++----------------------- 3 files changed, 104 insertions(+), 75 deletions(-) diff --git a/script.go b/script.go index 11b64aa0..f969a681 100644 --- a/script.go +++ b/script.go @@ -180,6 +180,16 @@ func isScriptHash(pops []parsedOpcode) bool { pops[2].opcode.value == OP_EQUAL } +// IsPayToScriptHash returns true if the script is in the standard +// Pay-To-Script-Hash format, false otherwise. +func IsPayToScriptHash(script []byte) bool { + pops, err := parseScript(script) + if err != nil { + return false + } + return isScriptHash(pops) +} + // isMultiSig returns true if the passed script is a multisig transaction, false // otherwise. func isMultiSig(pops []parsedOpcode) bool { diff --git a/script_test.go b/script_test.go index 67671d19..3797c9df 100644 --- a/script_test.go +++ b/script_test.go @@ -1675,6 +1675,13 @@ var scriptTypeTests = []scriptTypeTest{ }, scripttype: btcscript.TstNonStandardTy, }, + scriptTypeTest{ + name: "doesn't parse", + script: []byte{ + btcscript.OP_DATA_5, 0x1, 0x2, 0x3, 0x4, + }, + scripttype: btcscript.TstNonStandardTy, + }, } func testScriptType(t *testing.T, test *scriptTypeTest) { @@ -1691,6 +1698,17 @@ func TestScriptTypes(t *testing.T) { } } +func TestIsPayToScriptHash(t *testing.T) { + for _, test := range scriptTypeTests { + shouldBe := (test.scripttype == btcscript.TstScriptHashTy) + p2sh := btcscript.IsPayToScriptHash(test.script) + if p2sh != shouldBe { + t.Errorf("%s: epxected p2sh %v, got %v", test.name, + shouldBe, p2sh) + } + } +} + // This test sets the pc to a deliberately bad result then confirms that Step() // and Disasm fail correctly. func TestBadPC(t *testing.T) { diff --git a/test_coverage.txt b/test_coverage.txt index aff80910..2145d6b4 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -5,129 +5,130 @@ github.com/conformal/btcscript/script.go NewScript 100.00% (19/19) github.com/conformal/btcscript/stack.go asInt 100.00% (18/18) github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (17/17) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) -github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) +github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12) github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) -github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) -github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) -github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) +github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) +github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) +github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) -github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) -github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) -github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) +github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) +github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) -github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) -github.com/conformal/btcscript/script.go typeOfScript 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) +github.com/conformal/btcscript/script.go typeOfScript 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) +github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) +github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) -github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) -github.com/conformal/btcscript/script.go unparseScript 100.00% (4/4) -github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (4/4) -github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) +github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) +github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) +github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) +github.com/conformal/btcscript/script.go unparseScript 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) -github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) -github.com/conformal/btcscript/script.go setStack 100.00% (3/3) github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) -github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/conformal/btcscript/address.go ScriptToAddress 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) +github.com/conformal/btcscript/script.go setStack 100.00% (3/3) +github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) +github.com/conformal/btcscript/address.go ScriptToAddress 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) -github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) +github.com/conformal/btcscript/log.go init 100.00% (1/1) +github.com/conformal/btcscript/opcode.go init 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/conformal/btcscript/opcode.go init 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) -github.com/conformal/btcscript/log.go init 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.21% (55/56) github.com/conformal/btcscript/script.go parseScript 96.88% (31/32) github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) @@ -139,5 +140,5 @@ github.com/conformal/btcscript/opcode.go opcodeSha1 60.00% (3/5) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 95.90% (889/927) +github.com/conformal/btcscript -------------------------- 95.92% (893/931) From e5a275679578a51e869e313deca93f736d6380f1 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Thu, 27 Jun 2013 15:07:37 +0100 Subject: [PATCH 027/174] Test empty scripts and out of bounds for DisasmScript() give disasmscript a defined error return for out of bounds. --- opcode_test.go | 15 ++++++- script.go | 6 ++- test_coverage.txt | 106 +++++++++++++++++++++++----------------------- 3 files changed, 72 insertions(+), 55 deletions(-) diff --git a/opcode_test.go b/opcode_test.go index a23448b6..44134e7d 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -3885,12 +3885,25 @@ func testOpcode(t *testing.T, test *detailedTest) { // disassemble. var disScript, disPC string if test.disassembly != "" { - var err error + dis0, err := engine.DisasmScript(0) + if err != nil { + t.Errorf("failed to disassemble script0 for %s: %v", + test.name, err) + } + if dis0 != "" { + t.Errorf("disassembly of empty script gave \"%s\"", + test.name, dis0) + } disScript, err = engine.DisasmScript(1) if err != nil { t.Errorf("failed to disassemble script for %s: %v", test.name, err) } + _, err = engine.DisasmScript(2) + if err != btcscript.StackErrInvalidIndex { + t.Errorf("%s: got unexpected error for invalid "+ + "disassembly index: \"%v\"", test.name, err) + } } done := false diff --git a/script.go b/script.go index f969a681..551182d4 100644 --- a/script.go +++ b/script.go @@ -100,6 +100,10 @@ var StackErrInvalidParseType = errors.New("internal error: invalid parsetype fou // ony if the internal data tables are wrong. var StackErrInvalidAddrOffset = errors.New("internal error: invalid offset found") +// StackErrInvalidIndex is returned when an out-of-bounds index was passed to +// a function. +var StackErrInvalidIndex = errors.New("Invalid script index") + // Bip16Activation is the timestamp where BIP0016 is valid to use in the // blockchain. To be used to determine if BIP0016 should be called for or not. // This timestamp corresponds to Sun Apr 1 00:00:00 UTC 2012. @@ -521,7 +525,7 @@ func (m *Script) validPC() error { // ``idx''. Where 0 is the scriptSig and 1 is the scriptPubKey. func (m *Script) DisasmScript(idx int) (disstr string, err error) { if idx >= len(m.scripts) { - return "", fmt.Errorf("Invalid script index") + return "", StackErrInvalidIndex } for i := range m.scripts[idx] { disstr = disstr + m.disasm(idx, i) + "\n" diff --git a/test_coverage.txt b/test_coverage.txt index 2145d6b4..8e79227d 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -59,80 +59,80 @@ github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) -github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) -github.com/conformal/btcscript/script.go getStack 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) -github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) -github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) -github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) -github.com/conformal/btcscript/script.go unparseScript 100.00% (4/4) +github.com/conformal/btcscript/script.go getStack 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) +github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) +github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) -github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) -github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) +github.com/conformal/btcscript/script.go unparseScript 100.00% (4/4) +github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) +github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) github.com/conformal/btcscript/script.go setStack 100.00% (3/3) github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) +github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) +github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) +github.com/conformal/btcscript/address.go ScriptToAddress 100.00% (2/2) github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) -github.com/conformal/btcscript/address.go ScriptToAddress 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) -github.com/conformal/btcscript/log.go init 100.00% (1/1) -github.com/conformal/btcscript/opcode.go init 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go init 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) +github.com/conformal/btcscript/log.go init 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.21% (55/56) github.com/conformal/btcscript/script.go parseScript 96.88% (31/32) github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) -github.com/conformal/btcscript/script.go Script.DisasmScript 80.00% (4/5) github.com/conformal/btcscript/script.go Script.CheckErrorCondition 78.57% (11/14) github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) github.com/conformal/btcscript/script.go Script.calcScriptHash 71.43% (25/35) @@ -140,5 +140,5 @@ github.com/conformal/btcscript/opcode.go opcodeSha1 60.00% (3/5) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 95.92% (893/931) +github.com/conformal/btcscript -------------------------- 96.03% (894/931) From 89578c985ac3be6f7ab768bead547bb103022dfc Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Thu, 27 Jun 2013 16:15:32 +0100 Subject: [PATCH 028/174] add basic test for OP_SHA1 yup, it produces the sha of the data. --- opcode_test.go | 9 ++++ test_coverage.txt | 112 +++++++++++++++++++++++----------------------- 2 files changed, 65 insertions(+), 56 deletions(-) diff --git a/opcode_test.go b/opcode_test.go index 44134e7d..d0420e33 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -2004,6 +2004,15 @@ var detailedTests = []detailedTest{ expectedReturn: btcscript.StackErrUnderflow, disassembly: "OP_SHA1", }, + { + name: "OP_SHA1", + before: [][]byte{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, + script: []byte{btcscript.OP_SHA1}, + after: [][]byte{{0x5d, 0x21, 0x1b, 0xad, 0x8f, 0x4e, + 0xe7, 0x0e, 0x16, 0xc7, 0xd3, 0x43, 0xa8, 0x38, 0xfc, + 0x34, 0x4a, 0x1e, 0xd9, 0x61}}, + disassembly: "OP_SHA1", + }, { name: "OP_SHA256 no args", before: [][]byte{}, diff --git a/test_coverage.txt b/test_coverage.txt index 8e79227d..c7dd493e 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -52,6 +52,7 @@ github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) @@ -60,85 +61,84 @@ github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (4/4) -github.com/conformal/btcscript/script.go getStack 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) -github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) -github.com/conformal/btcscript/script.go unparseScript 100.00% (4/4) -github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) -github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) +github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) +github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (4/4) +github.com/conformal/btcscript/script.go unparseScript 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) +github.com/conformal/btcscript/script.go getStack 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) +github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) +github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) github.com/conformal/btcscript/script.go setStack 100.00% (3/3) github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) -github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) -github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) -github.com/conformal/btcscript/address.go ScriptToAddress 100.00% (2/2) -github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) +github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/conformal/btcscript/address.go ScriptToAddress 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) +github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go init 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) +github.com/conformal/btcscript/log.go init 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) -github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go init 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) -github.com/conformal/btcscript/log.go init 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) -github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) +github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.21% (55/56) github.com/conformal/btcscript/script.go parseScript 96.88% (31/32) github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) github.com/conformal/btcscript/script.go Script.CheckErrorCondition 78.57% (11/14) github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) github.com/conformal/btcscript/script.go Script.calcScriptHash 71.43% (25/35) -github.com/conformal/btcscript/opcode.go opcodeSha1 60.00% (3/5) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 96.03% (894/931) +github.com/conformal/btcscript -------------------------- 96.24% (896/931) From c41330e772e033fa1e5ff09390f2e66b0504293a Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Fri, 28 Jun 2013 00:46:34 +0100 Subject: [PATCH 029/174] Add basic test for if internal opcode definitions are buggy. --- internal_test.go | 19 ++++++ script.go | 6 ++ test_coverage.txt | 163 +++++++++++++++++++++++----------------------- 3 files changed, 107 insertions(+), 81 deletions(-) diff --git a/internal_test.go b/internal_test.go index 9e282c66..3240abb0 100644 --- a/internal_test.go +++ b/internal_test.go @@ -116,3 +116,22 @@ func TestBadPkFormat(t *testing.T) { } } + +// Internal tests for opcodde parsing with bad data templates. +func TestParseOpcode(t *testing.T) { + fakemap := make(map[byte]*opcode) + // deep copy + for k, v := range opcodemap { + fakemap[k] = v + } + // wrong length -8. + fakemap[OP_PUSHDATA4] = &opcode{value: OP_PUSHDATA4, + name: "OP_PUSHDATA4", length: -8, opfunc: opcodePushData} + + // this script would be fine if -8 was a valid length. + _, err := parseScriptTemplate([]byte{OP_PUSHDATA4, 0x1, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}, fakemap) + if err == nil { + t.Errorf("no error with dodgy opcode map!") + } +} diff --git a/script.go b/script.go index 551182d4..110154d6 100644 --- a/script.go +++ b/script.go @@ -258,6 +258,12 @@ func typeOfScript(pops []parsedOpcode) scriptType { // parseScript preparses the script in bytes into a list of parsedOpcodes while // applying a number of sanity checks. func parseScript(script []byte) ([]parsedOpcode, error) { + return parseScriptTemplate(script, opcodemap) +} + +// parseScriptTemplate is the same as parseScript but allows the passing of the +// template list for testing purposes. +func parseScriptTemplate(script []byte, opcodemap map[byte]*opcode) ([]parsedOpcode, error) { retScript := []parsedOpcode{} for i := 0; i < len(script); { instr := script[i] diff --git a/test_coverage.txt b/test_coverage.txt index c7dd493e..9556b1bd 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -1,6 +1,7 @@ github.com/conformal/btcscript/address.go scriptToAddressTemplate 100.00% (58/58) github.com/conformal/btcscript/script.go Script.Step 100.00% (37/37) +github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (32/32) github.com/conformal/btcscript/script.go NewScript 100.00% (19/19) github.com/conformal/btcscript/stack.go asInt 100.00% (18/18) github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (17/17) @@ -12,127 +13,127 @@ github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) -github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) -github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) +github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) +github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) +github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) +github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) github.com/conformal/btcscript/script.go typeOfScript 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) +github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) -github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) -github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) -github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (4/4) -github.com/conformal/btcscript/script.go unparseScript 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) -github.com/conformal/btcscript/script.go getStack 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) -github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) -github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) -github.com/conformal/btcscript/script.go setStack 100.00% (3/3) +github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) +github.com/conformal/btcscript/script.go unparseScript 100.00% (4/4) +github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) +github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) +github.com/conformal/btcscript/script.go getStack 100.00% (4/4) +github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (4/4) github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) +github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) -github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/conformal/btcscript/address.go ScriptToAddress 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) +github.com/conformal/btcscript/script.go setStack 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) +github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/conformal/btcscript/address.go ScriptToAddress 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) -github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) +github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) +github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) github.com/conformal/btcscript/opcode.go init 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) +github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) -github.com/conformal/btcscript/log.go init 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) -github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) -github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) +github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) +github.com/conformal/btcscript/log.go init 100.00% (1/1) github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.21% (55/56) -github.com/conformal/btcscript/script.go parseScript 96.88% (31/32) github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) github.com/conformal/btcscript/script.go Script.CheckErrorCondition 78.57% (11/14) github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) @@ -140,5 +141,5 @@ github.com/conformal/btcscript/script.go Script.calcScriptHash 71.43% (25/35) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 96.24% (896/931) +github.com/conformal/btcscript -------------------------- 96.35% (898/932) From 4d31b2c850c31b81d64c3cb53545352f04f09ec9 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Fri, 28 Jun 2013 01:15:10 +0100 Subject: [PATCH 030/174] Remove blurb about 100% coverage and replace with comprehensive. btcscript contains an amount of debug logging that is very useful to have. We have agreed that testing this isn't realy practical or indeed really useful and thus is rather unlikely to grow test coverage any time soon. --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 28662ad6..b8472a8e 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ btcscript ========= -Package btcscript implements the bitcoin transaction scripts. There is a test -suite which is aiming to reach 100% code coverage. See -`test_coverage.txt` for the current coverage (using gocov). On a -UNIX-like OS, the script `cov_report.sh` can be used to generate the -report. Package btcscript is licensed under the liberal ISC license. +Package btcscript implements the bitcoin transaction scripts. There is +a comprehensive test suite. `test_coverage.txt` contains the current +coverage statistics (generated using gocov). On a UNIX-like OS, the +script `cov_report.sh` can be used to generate the report. Package +btcscript is licensed under the liberal ISC license. This package is one of the core packages from btcd, an alternative full-node implementation of bitcoin which is under active development by Conformal. From bedaddb790b19cfdf8ca6ca112cdca0cd032db9c Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Fri, 5 Jul 2013 00:54:55 +0100 Subject: [PATCH 031/174] add GetScriptClass to return the internal script type of a script. To be used to tell which class a script is (multisig, scripthash, pubkey, pkhash, or nonstandard) --- internal_test.go | 18 ---------- script.go | 38 ++++++++++++++-------- script_test.go | 26 +++++++-------- test_coverage.txt | 83 ++++++++++++++++++++++++----------------------- 4 files changed, 79 insertions(+), 86 deletions(-) diff --git a/internal_test.go b/internal_test.go index 3240abb0..d957ebb8 100644 --- a/internal_test.go +++ b/internal_test.go @@ -29,24 +29,6 @@ func TstRemoveOpcodeByData(pkscript []byte, data []byte) ([]byte, error) { return unparseScript(pops), nil } -type TstScriptType scriptType - -const ( - TstPubKeyTy TstScriptType = TstScriptType(pubKeyTy) - TstPubKeyHashTy = TstScriptType(pubKeyHashTy) - TstScriptHashTy = TstScriptType(scriptHashTy) - TstMultiSigTy = TstScriptType(multiSigTy) - TstNonStandardTy = TstScriptType(nonStandardTy) -) - -func TstTypeOfScript(script []byte) TstScriptType { - pops, err := parseScript(script) - if err != nil { - return TstNonStandardTy - } - return TstScriptType(typeOfScript(pops)) -} - // TestSetPC allows the test modules to set the program counter to whatever they // want. func (s *Script) TstSetPC(script, off int) { diff --git a/script.go b/script.go index 110154d6..f4e6f555 100644 --- a/script.go +++ b/script.go @@ -125,16 +125,16 @@ const ( MaxScriptElementSize = 520 // Max bytes pushable to the stack. ) -// ScriptType is an enumeration for the list of standard types of script. -type scriptType byte +// ScriptClass is an enumeration for the list of standard types of script. +type ScriptClass byte -// Types of script payment known about in the blockchain. +// Classes of script payment known about in the blockchain. const ( - pubKeyTy scriptType = iota // Pay pubkey. - pubKeyHashTy // Pay pubkey hash. - scriptHashTy // Pay to script hash. - multiSigTy // Multi signature. - nonStandardTy // None of the above. + PubKeyTy ScriptClass = iota // Pay pubkey. + PubKeyHashTy // Pay pubkey hash. + ScriptHashTy // Pay to script hash. + MultiSigTy // Multi signature. + NonStandardTy // None of the above. ) // Script is the virtual machine that executes btcscripts. @@ -237,21 +237,31 @@ func isPushOnly(pops []parsedOpcode) bool { return true } +// GetScriptClass returns the class of the script passed. If the script does not +// parse then NonStandardTy will be returned. +func GetScriptClass(script []byte) ScriptClass { + pops, err := parseScript(script) + if err != nil { + return NonStandardTy + } + return typeOfScript(pops) +} + // scriptType returns the type of the script being inspected from the known // standard types. -func typeOfScript(pops []parsedOpcode) scriptType { +func typeOfScript(pops []parsedOpcode) ScriptClass { // XXX dubious optimisation: order these in order of popularity in the // blockchain if isPubkey(pops) { - return pubKeyTy + return PubKeyTy } else if isPubkeyHash(pops) { - return pubKeyHashTy + return PubKeyHashTy } else if isScriptHash(pops) { - return scriptHashTy + return ScriptHashTy } else if isMultiSig(pops) { - return multiSigTy + return MultiSigTy } - return nonStandardTy + return NonStandardTy } diff --git a/script_test.go b/script_test.go index 3797c9df..0e2751fc 100644 --- a/script_test.go +++ b/script_test.go @@ -1536,7 +1536,7 @@ func TestRemoveOpcodeByDatas(t *testing.T) { type scriptTypeTest struct { name string script []byte - scripttype btcscript.TstScriptType + scripttype btcscript.ScriptClass } var scriptTypeTests = []scriptTypeTest{ @@ -1555,7 +1555,7 @@ var scriptTypeTests = []scriptTypeTest{ 0x12, 0xa3, btcscript.OP_CHECKSIG, }, - scripttype: btcscript.TstPubKeyTy, + scripttype: btcscript.PubKeyTy, }, // tx 599e47a8114fe098103663029548811d2651991b62397e057f0c863c2bc9f9ea scriptTypeTest{ @@ -1570,7 +1570,7 @@ var scriptTypeTests = []scriptTypeTest{ btcscript.OP_EQUALVERIFY, btcscript.OP_CHECKSIG, }, - scripttype: btcscript.TstPubKeyHashTy, + scripttype: btcscript.PubKeyHashTy, }, // part of tx 6d36bc17e947ce00bb6f12f8e7a56a1585c5a36188ffa2b05e10b4743273a74b // codeseparator parts have been elided. (bitcoind's checks for multisig @@ -1587,7 +1587,7 @@ var scriptTypeTests = []scriptTypeTest{ btcscript.OP_TRUE, btcscript.OP_CHECK_MULTISIG, }, - scripttype: btcscript.TstMultiSigTy, + scripttype: btcscript.MultiSigTy, }, // tx e5779b9e78f9650debc2893fd9636d827b26b4ddfa6a8172fe8708c924f5c39d // P2SH @@ -1601,7 +1601,7 @@ var scriptTypeTests = []scriptTypeTest{ 0xae, 0x88, btcscript.OP_EQUAL, }, - scripttype: btcscript.TstScriptHashTy, + scripttype: btcscript.ScriptHashTy, }, // The next few are almost multisig (it is the more complex script type) // but with various changes to make it fail. @@ -1618,7 +1618,7 @@ var scriptTypeTests = []scriptTypeTest{ btcscript.OP_TRUE, btcscript.OP_CHECK_MULTISIG, }, - scripttype: btcscript.TstNonStandardTy, + scripttype: btcscript.NonStandardTy, }, scriptTypeTest{ name: "strange 2", @@ -1629,7 +1629,7 @@ var scriptTypeTests = []scriptTypeTest{ btcscript.OP_TRUE, btcscript.OP_CHECK_MULTISIG, }, - scripttype: btcscript.TstNonStandardTy, + scripttype: btcscript.NonStandardTy, }, scriptTypeTest{ name: "strange 3", @@ -1649,7 +1649,7 @@ var scriptTypeTests = []scriptTypeTest{ // No number. btcscript.OP_CHECK_MULTISIG, }, - scripttype: btcscript.TstNonStandardTy, + scripttype: btcscript.NonStandardTy, }, scriptTypeTest{ name: "strange 4", @@ -1664,7 +1664,7 @@ var scriptTypeTests = []scriptTypeTest{ btcscript.OP_TRUE, btcscript.OP_CHECKMULTISIGVERIFY, }, - scripttype: btcscript.TstNonStandardTy, + scripttype: btcscript.NonStandardTy, }, scriptTypeTest{ name: "strange 5", @@ -1673,19 +1673,19 @@ var scriptTypeTests = []scriptTypeTest{ btcscript.OP_TRUE, btcscript.OP_CHECK_MULTISIG, }, - scripttype: btcscript.TstNonStandardTy, + scripttype: btcscript.NonStandardTy, }, scriptTypeTest{ name: "doesn't parse", script: []byte{ btcscript.OP_DATA_5, 0x1, 0x2, 0x3, 0x4, }, - scripttype: btcscript.TstNonStandardTy, + scripttype: btcscript.NonStandardTy, }, } func testScriptType(t *testing.T, test *scriptTypeTest) { - scripttype := btcscript.TstTypeOfScript(test.script) + scripttype := btcscript.GetScriptClass(test.script) if scripttype != test.scripttype { t.Errorf("%s: expected %s got %s", test.name, test.scripttype, scripttype) @@ -1700,7 +1700,7 @@ func TestScriptTypes(t *testing.T) { func TestIsPayToScriptHash(t *testing.T) { for _, test := range scriptTypeTests { - shouldBe := (test.scripttype == btcscript.TstScriptHashTy) + shouldBe := (test.scripttype == btcscript.ScriptHashTy) p2sh := btcscript.IsPayToScriptHash(test.script) if p2sh != shouldBe { t.Errorf("%s: epxected p2sh %v, got %v", test.name, diff --git a/test_coverage.txt b/test_coverage.txt index 9556b1bd..cb1626db 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -8,131 +8,132 @@ github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (17/17) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) -github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12) github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) +github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) +github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) +github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) -github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) -github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) -github.com/conformal/btcscript/script.go typeOfScript 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) +github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) +github.com/conformal/btcscript/script.go typeOfScript 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) github.com/conformal/btcscript/script.go unparseScript 100.00% (4/4) github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) +github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (4/4) -github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) -github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) github.com/conformal/btcscript/script.go setStack 100.00% (3/3) +github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) +github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) -github.com/conformal/btcscript/address.go ScriptToAddress 100.00% (2/2) +github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) +github.com/conformal/btcscript/address.go ScriptToAddress 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) -github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) github.com/conformal/btcscript/opcode.go init 100.00% (1/1) github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) +github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) github.com/conformal/btcscript/log.go init 100.00% (1/1) -github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.21% (55/56) github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) github.com/conformal/btcscript/script.go Script.CheckErrorCondition 78.57% (11/14) @@ -141,5 +142,5 @@ github.com/conformal/btcscript/script.go Script.calcScriptHash 71.43% (25/35) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 96.35% (898/932) +github.com/conformal/btcscript -------------------------- 96.37% (902/936) From eb5de559ffca7572c5d7e3aad3adea2dd3999acc Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Sat, 6 Jul 2013 11:58:28 -0500 Subject: [PATCH 032/174] Fix a couple of comment typos for the word execute. --- script.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/script.go b/script.go index f4e6f555..75b2c867 100644 --- a/script.go +++ b/script.go @@ -46,7 +46,7 @@ var StackErrInvalidOpcode = errors.New("Invalid Opcode") // encountered. var StackErrReservedOpcode = errors.New("Reserved Opcode") -// StackErrEarlyReturn is returned when OP_RETURN is exectured in the script. +// StackErrEarlyReturn is returned when OP_RETURN is executed in the script. var StackErrEarlyReturn = errors.New("Script returned early") // StackErrNoIf is returned if an OP_ELSE or OP_ENDIF is encountered without @@ -378,7 +378,7 @@ func NewScript(scriptSig []byte, scriptPubKey []byte, txidx int, tx *btcwire.Msg return &m, nil } -// Execute will execturte all script in the script engine and return either nil +// Execute will execute all script in the script engine and return either nil // for successful validation or an error if one occurred. func (s *Script) Execute() (err error) { done := false From e7f9415e4f5348c479d4f27ccc4c1767a50a4854 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Thu, 25 Jul 2013 14:27:58 +0100 Subject: [PATCH 033/174] Return 0 for bad scripts from sigops code instead of an error. matches how bitcoind behaves. --- opcode_test.go | 30 ++---------------------------- script.go | 22 +++++++++++----------- script_test.go | 32 ++------------------------------ 3 files changed, 15 insertions(+), 69 deletions(-) diff --git a/opcode_test.go b/opcode_test.go index d0420e33..e5423d20 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -4004,20 +4004,7 @@ func TestDisasmStrings(t *testing.T) { // us coverage over a wider range of opcodes. func TestSigOps(t *testing.T) { for _, test := range detailedTests { - count, err := btcscript.GetSigOpCount(test.script) - if err != nil { - if err != test.disassemblyerr { - t.Errorf("%s: unexpected error. exp \"%v\""+ - "got \"%v\"", test.name, - test.disassemblyerr, err) - } - continue - } - if test.disassemblyerr != nil { - t.Errorf("%s: no error when expected \"%v\"", - test.name, test.disassemblyerr) - continue - } + count := btcscript.GetSigOpCount(test.script) if count != test.nSigOps { t.Errorf("%s: expected count of %d, got %d", test.name, test.nSigOps, count) @@ -4035,21 +4022,8 @@ func TestSigOps(t *testing.T) { // using real transactions to provide a bit more coverage. func TestPreciseSigOps(t *testing.T) { for _, test := range detailedTests { - count, err := btcscript.GetPreciseSigOpCount( + count := btcscript.GetPreciseSigOpCount( []byte{btcscript.OP_1}, test.script, false) - if err != nil { - if err != test.disassemblyerr { - t.Errorf("%s: unexpected error. exp \"%v\""+ - "got \"%v\"", test.name, - test.disassemblyerr, err) - } - continue - } - if test.disassemblyerr != nil { - t.Errorf("%s: no error when expected \"%v\"", - test.name, test.disassemblyerr) - continue - } if count != test.nPreciseSigOps { t.Errorf("%s: expected count of %d, got %d", test.name, test.nPreciseSigOps, count) diff --git a/script.go b/script.go index 75b2c867..4e7dcf91 100644 --- a/script.go +++ b/script.go @@ -763,51 +763,51 @@ func (s *Script) SetAltStack(data [][]byte) { // GetSigOpCount provides a quick count of the number of signature operations // in a script. a CHECKSIG operations counts for 1, and a CHECK_MULTISIG for 20. -func GetSigOpCount(script []byte) (int, error) { +func GetSigOpCount(script []byte) int { pops, err := parseScript(script) if err != nil { - return 0, err + return 0 } - return getSigOpCount(pops, false), nil + return getSigOpCount(pops, false) } // GetPreciseSigOpCount returns the number of signature operations in // scriptPubKey. If bip16 is true then scriptSig may be searched for the // Pay-To-Script-Hash script in order to find the precise number of signature // operations in the transaction. -func GetPreciseSigOpCount(scriptSig, scriptPubKey []byte, bip16 bool) (int, error) { +func GetPreciseSigOpCount(scriptSig, scriptPubKey []byte, bip16 bool) int { pops, err := parseScript(scriptPubKey) if err != nil { - return 0, err + return 0 } // non P2SH transactions just treated as normal. if !(bip16 && isScriptHash(pops)) { - return getSigOpCount(pops, true), nil + return getSigOpCount(pops, true) } // Ok so this is P2SH, get the contained script and count it.. sigPops, err := parseScript(scriptSig) if err != nil { - return 0, err + return 0 } if !isPushOnly(sigPops) || len(sigPops) == 0 { - return 0, nil + return 0 } shScript := sigPops[len(sigPops)-1].data // Means that sigPops is jus OP_1 - OP_16, no sigops there. if shScript == nil { - return 0, nil + return 0 } shPops, err := parseScript(shScript) if err != nil { - return 0, err + return 0 } - return getSigOpCount(shPops, true), nil + return getSigOpCount(shPops, true) } // getSigOpCount is the implementation function for counting the number of diff --git a/script_test.go b/script_test.go index 0e2751fc..1a420f66 100644 --- a/script_test.go +++ b/script_test.go @@ -21,7 +21,6 @@ type txTest struct { err error // Failure of Executre shouldFail bool // Execute should fail with nonspecified error. nSigOps int // result of GetPreciseSigOpsCount - sigOpsErr error // failure of GetPreciseSigOpsCount() } var txTests = []txTest{ @@ -1079,7 +1078,6 @@ var txTests = []txTest{ idx: 0, err: btcscript.StackErrShortScript, bip16: true, - sigOpsErr: btcscript.StackErrShortScript, }, txTest{ // sigscript changed so to be non pushonly. @@ -1247,22 +1245,9 @@ func TestGetPreciseSignOps(t *testing.T) { // First we go over the range of tests in testTx and count the sigops in // them. for _, test := range txTests { - count, err := btcscript.GetPreciseSigOpCount( + count := btcscript.GetPreciseSigOpCount( test.tx.TxIn[test.idx].SignatureScript, test.pkScript, test.bip16) - // all tx currently parse - if err != nil { - if err != test.sigOpsErr { - t.Errorf("%s: unexpected error. got \"%v\"", - test.name, err) - } - continue - } - if test.sigOpsErr != nil { - t.Errorf("%s: expected error \"%v\" but got success", - test.name, err) - continue - } if count != test.nSigOps { t.Errorf("%s: expected count of %d, got %d", test.name, test.nSigOps, count) @@ -1321,21 +1306,8 @@ func TestGetPreciseSignOps(t *testing.T) { btcscript.OP_EQUAL, } for _, test := range psocTests { - count, err := btcscript.GetPreciseSigOpCount( + count := btcscript.GetPreciseSigOpCount( test.scriptSig, pkScript, true) - // all tx currently parse - if err != nil { - if err != test.err { - t.Errorf("%s: unexpected error. got \"%v\" exp: \"%v\"", - test.name, err, test.err) - } - continue - } - if test.err != nil { - t.Errorf("%s: expected error \"%v\" got none", - test.name, test.err) - continue - } if count != test.nSigOps { t.Errorf("%s: expected count of %d, got %d", test.name, test.nSigOps, count) From fe2233c851a59c3f646f63755372cd20fcf53e22 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Thu, 25 Jul 2013 15:40:11 +0100 Subject: [PATCH 034/174] Make count sigops always count up to the point of parse failure. We do this by allowing the parser to return the list of parsed objects (it is an internal only api anyway) and then we use this in the sigops counting and ignore the error. This change due to bitcoind compatability. --- script.go | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/script.go b/script.go index 4e7dcf91..25fe77e9 100644 --- a/script.go +++ b/script.go @@ -272,14 +272,15 @@ func parseScript(script []byte) ([]parsedOpcode, error) { } // parseScriptTemplate is the same as parseScript but allows the passing of the -// template list for testing purposes. +// template list for testing purposes. On error we return the list of parsed +// opcodes so far. func parseScriptTemplate(script []byte, opcodemap map[byte]*opcode) ([]parsedOpcode, error) { retScript := []parsedOpcode{} for i := 0; i < len(script); { instr := script[i] op, ok := opcodemap[instr] if !ok { - return nil, StackErrInvalidOpcode + return retScript, StackErrInvalidOpcode } pop := parsedOpcode{opcode: op} // parse data out of instruction. @@ -289,7 +290,7 @@ func parseScriptTemplate(script []byte, opcodemap map[byte]*opcode) ([]parsedOpc i++ case op.length > 1: if len(script[i:]) < op.length { - return nil, StackErrShortScript + return retScript, StackErrShortScript } // slice out the data. pop.data = script[i+1 : i+op.length] @@ -306,7 +307,9 @@ func parseScriptTemplate(script []byte, opcodemap map[byte]*opcode) ([]parsedOpc case -4: l, err = scriptUInt32(script[off:]) default: - return nil, fmt.Errorf("invalid opcode length %d", op.length) + return retScript, + fmt.Errorf("invalid opcode length %d", + op.length) } if err != nil { @@ -314,10 +317,10 @@ func parseScriptTemplate(script []byte, opcodemap map[byte]*opcode) ([]parsedOpc } off = i + 1 - op.length // beginning of data if int(l) > len(script[off:]) { - return nil, StackErrShortScript + return retScript, StackErrShortScript } if l > MaxScriptElementSize { - return nil, StackErrElementTooBig + return retScript, StackErrElementTooBig } pop.data = script[off : off+int(l)] i += 1 - op.length + int(l) @@ -763,11 +766,12 @@ func (s *Script) SetAltStack(data [][]byte) { // GetSigOpCount provides a quick count of the number of signature operations // in a script. a CHECKSIG operations counts for 1, and a CHECK_MULTISIG for 20. +// If the script fails to parse, then the count up to the point of failure is +// returned. func GetSigOpCount(script []byte) int { - pops, err := parseScript(script) - if err != nil { - return 0 - } + // We don't check error since parseScript returns the parsed-up-to-error + // list of pops. + pops, _ := parseScript(script) return getSigOpCount(pops, false) } @@ -775,12 +779,12 @@ func GetSigOpCount(script []byte) int { // GetPreciseSigOpCount returns the number of signature operations in // scriptPubKey. If bip16 is true then scriptSig may be searched for the // Pay-To-Script-Hash script in order to find the precise number of signature -// operations in the transaction. +// operations in the transaction. If the script fails to parse, then the +// count up to the point of failure is returned. func GetPreciseSigOpCount(scriptSig, scriptPubKey []byte, bip16 bool) int { - pops, err := parseScript(scriptPubKey) - if err != nil { - return 0 - } + // We don't check error since parseScript returns the parsed-up-to-error + // list of pops. + pops, _ := parseScript(scriptPubKey) // non P2SH transactions just treated as normal. if !(bip16 && isScriptHash(pops)) { return getSigOpCount(pops, true) @@ -802,10 +806,7 @@ func GetPreciseSigOpCount(scriptSig, scriptPubKey []byte, bip16 bool) int { return 0 } - shPops, err := parseScript(shScript) - if err != nil { - return 0 - } + shPops, _ := parseScript(shScript) return getSigOpCount(shPops, true) } From 22c29c4316e047217352647ac52b77f8805295d0 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Mon, 29 Jul 2013 16:17:11 +0100 Subject: [PATCH 035/174] Perform pushed length checks at exec time, not parse. To match bitcoind behaviour. Fix tests to agree with this direction. --- opcode.go | 5 +++ opcode_test.go | 2 +- script.go | 3 -- test_coverage.txt | 88 +++++++++++++++++++++++------------------------ 4 files changed, 50 insertions(+), 48 deletions(-) diff --git a/opcode.go b/opcode.go index 613fd74f..2edde0ae 100644 --- a/opcode.go +++ b/opcode.go @@ -736,6 +736,11 @@ func opcodeFalse(op *parsedOpcode, s *Script) error { } func opcodePushData(op *parsedOpcode, s *Script) error { + // This max script element test must occur at execution time instead + // of parse time to match bitcoind behaviour. + if len(op.data) > MaxScriptElementSize { + return StackErrElementTooBig + } s.dstack.PushByteArray(op.data) return nil } diff --git a/opcode_test.go b/opcode_test.go index e5423d20..5df53f3c 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -3278,7 +3278,7 @@ var detailedTests = []detailedTest{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, expectedReturn: btcscript.StackErrElementTooBig, // element too big is a parse error. - disassemblyerr: btcscript.StackErrElementTooBig, + disassembly: "0102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708", }, { name: "OP_CAT disabled", diff --git a/script.go b/script.go index 25fe77e9..904be765 100644 --- a/script.go +++ b/script.go @@ -319,9 +319,6 @@ func parseScriptTemplate(script []byte, opcodemap map[byte]*opcode) ([]parsedOpc if int(l) > len(script[off:]) { return retScript, StackErrShortScript } - if l > MaxScriptElementSize { - return retScript, StackErrElementTooBig - } pop.data = script[off : off+int(l)] i += 1 - op.length + int(l) } diff --git a/test_coverage.txt b/test_coverage.txt index cb1626db..a9469f3e 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -1,68 +1,69 @@ github.com/conformal/btcscript/address.go scriptToAddressTemplate 100.00% (58/58) github.com/conformal/btcscript/script.go Script.Step 100.00% (37/37) -github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (32/32) +github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (30/30) github.com/conformal/btcscript/script.go NewScript 100.00% (19/19) github.com/conformal/btcscript/stack.go asInt 100.00% (18/18) -github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (17/17) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) +github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) +github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12) github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) -github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12) -github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) +github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) -github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) +github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) -github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) github.com/conformal/btcscript/script.go typeOfScript 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) +github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) @@ -79,61 +80,60 @@ github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) -github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (4/4) -github.com/conformal/btcscript/script.go setStack 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) +github.com/conformal/btcscript/script.go setStack 100.00% (3/3) github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) -github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) +github.com/conformal/btcscript/address.go ScriptToAddress 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/conformal/btcscript/address.go ScriptToAddress 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) +github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) -github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) github.com/conformal/btcscript/opcode.go init 100.00% (1/1) github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/log.go init 100.00% (1/1) +github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) -github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) -github.com/conformal/btcscript/log.go init 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) +github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.21% (55/56) github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) github.com/conformal/btcscript/script.go Script.CheckErrorCondition 78.57% (11/14) @@ -142,5 +142,5 @@ github.com/conformal/btcscript/script.go Script.calcScriptHash 71.43% (25/35) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 96.37% (902/936) +github.com/conformal/btcscript -------------------------- 96.34% (896/930) From 927d846f067df1ef6f4dbc615fe592a7c2d4fd33 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Tue, 30 Jul 2013 22:45:26 +0100 Subject: [PATCH 036/174] Handle bad input in sighash single. The bitcoinj test suite actually uses it (the only thing i've seen that does). Specifically it uses it with a bad input which returns a hash of 1. --- script.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/script.go b/script.go index 904be765..20e5ed1f 100644 --- a/script.go +++ b/script.go @@ -653,7 +653,18 @@ func (s *Script) calcScriptHash(script []parsedOpcode, hashType byte) []byte { } } case SigHashSingle: - // resize output array to up to and including current output + if txidx >= len(txCopy.TxOut) { + // This was created by a buggy implementation. + // In this case we do the same as bitcoind and bitcoinj + // and return 1 (as a uint256 little endian) as an + // error. Unfortunately this was not checked anywhere + // and thus is treated as the actual + // hash. + hash := make([]byte, 32) + hash[0] = 0x01 + return hash + } + // Resize output array to up to and including requested index. txCopy.TxOut = txCopy.TxOut[:txidx+1] // all but current output get zeroed out for i := 0; i < txidx; i++ { From 118014a5b4323656fd2dc910359e45def2761523 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Wed, 31 Jul 2013 01:31:27 +0100 Subject: [PATCH 037/174] gofmt. --- script.go | 12 ++++++------ script_test.go | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/script.go b/script.go index 20e5ed1f..8e6fd052 100644 --- a/script.go +++ b/script.go @@ -131,10 +131,10 @@ type ScriptClass byte // Classes of script payment known about in the blockchain. const ( PubKeyTy ScriptClass = iota // Pay pubkey. - PubKeyHashTy // Pay pubkey hash. - ScriptHashTy // Pay to script hash. - MultiSigTy // Multi signature. - NonStandardTy // None of the above. + PubKeyHashTy // Pay pubkey hash. + ScriptHashTy // Pay to script hash. + MultiSigTy // Multi signature. + NonStandardTy // None of the above. ) // Script is the virtual machine that executes btcscripts. @@ -309,7 +309,7 @@ func parseScriptTemplate(script []byte, opcodemap map[byte]*opcode) ([]parsedOpc default: return retScript, fmt.Errorf("invalid opcode length %d", - op.length) + op.length) } if err != nil { @@ -787,7 +787,7 @@ func GetSigOpCount(script []byte) int { // GetPreciseSigOpCount returns the number of signature operations in // scriptPubKey. If bip16 is true then scriptSig may be searched for the // Pay-To-Script-Hash script in order to find the precise number of signature -// operations in the transaction. If the script fails to parse, then the +// operations in the transaction. If the script fails to parse, then the // count up to the point of failure is returned. func GetPreciseSigOpCount(scriptSig, scriptPubKey []byte, bip16 bool) int { // We don't check error since parseScript returns the parsed-up-to-error diff --git a/script_test.go b/script_test.go index 1a420f66..ac05927a 100644 --- a/script_test.go +++ b/script_test.go @@ -1075,9 +1075,9 @@ var txTests = []txTest{ 0xba, 0x67, btcscript.OP_EQUAL, }, - idx: 0, - err: btcscript.StackErrShortScript, - bip16: true, + idx: 0, + err: btcscript.StackErrShortScript, + bip16: true, }, txTest{ // sigscript changed so to be non pushonly. From 26fb20e4ed73385b5bf3bbc04754831ac2f53bb5 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Mon, 5 Aug 2013 15:08:28 -0500 Subject: [PATCH 038/174] Remove need for protocol version. This commit modifies the code to no longer require a protocol version. It does this by making use of the new Serialize function in btcwire. Unfortuantely this does entail a public API change which I generally don't like to do, but eliminating the usage of the protocol version throughout the codebase was important enough to warrant the change. --- README.md | 3 +-- doc.go | 7 +++---- opcode_test.go | 4 ++-- script.go | 6 ++---- script_test.go | 6 +++--- 5 files changed, 11 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index b8472a8e..bb00df62 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,7 @@ can be found at https://en.bitcoin.it/wiki/Script ```Go pkscript := txS.TxOut[origintxidx].PkScript engine, err := btcscript.NewScript(sigScript, pkscript, txInIdx, - txValidator, pver, - timestamp.After(btcscript.Bip16Activation)) + txValidator, timestamp.After(btcscript.Bip16Activation)) err = engine.Execute() ``` diff --git a/doc.go b/doc.go index 0fb28f23..ebca20c6 100644 --- a/doc.go +++ b/doc.go @@ -40,13 +40,12 @@ engine to validate a transaction. // ValidateTx validates the txIdx'th input of tx. The output transaction // corresponding to the this input is the txInIdx'th output of txIn. The - // block timestamp of tx is timestamp and the protocol version involved - // is pver. - func ValidateTx(tx *btcwire.MsgTx, txIdx int, txIn *btcwire.MsgTx, txInIdx int, pver int, timestamp time.Time) { + // block timestamp of tx is timestamp. + func ValidateTx(tx *btcwire.MsgTx, txIdx int, txIn *btcwire.MsgTx, txInIdx int, timestamp time.Time) { pkScript := txIn.TxOut[txInIdx].PkScript sigScript := tx.txIn[TxIdx] engine, err := btcscript.NewScript(sigScript, pkScript, txInIdx, - tx, pver, timestamp.After(btcscript.Bip16Activation)) + tx, timestamp.After(btcscript.Bip16Activation)) return engine.Execute() } diff --git a/opcode_test.go b/opcode_test.go index 5df53f3c..61eb31c0 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -494,7 +494,7 @@ func testScript(t *testing.T, script []byte) (err error) { tx.TxOut[0].PkScript = script engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript, - tx.TxOut[0].PkScript, 0, tx, 1, false) + tx.TxOut[0].PkScript, 0, tx, false) if err != nil { return err } @@ -3875,7 +3875,7 @@ func testOpcode(t *testing.T, test *detailedTest) { tx.TxOut[0].PkScript = test.script engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript, - tx.TxOut[0].PkScript, 0, tx, 1, false) + tx.TxOut[0].PkScript, 0, tx, false) if err != nil { if err != test.expectedReturn { t.Errorf("Error return not expected %s: %v %v", diff --git a/script.go b/script.go index 8e6fd052..581cf1eb 100644 --- a/script.go +++ b/script.go @@ -147,7 +147,6 @@ type Script struct { astack Stack // alt stack tx btcwire.MsgTx txidx int - pver uint32 condStack []int numOps int bip16 bool // treat execution as pay-to-script-hash @@ -341,7 +340,7 @@ func unparseScript(pops []parsedOpcode) []byte { // a signature script scriptSig and a pubkeyscript scriptPubKey. If bip16 is // true then it will be treated as if the bip16 threshhold has passed and thus // pay-to-script hash transactions will be fully validated. -func NewScript(scriptSig []byte, scriptPubKey []byte, txidx int, tx *btcwire.MsgTx, pver uint32, bip16 bool) (*Script, error) { +func NewScript(scriptSig []byte, scriptPubKey []byte, txidx int, tx *btcwire.MsgTx, bip16 bool) (*Script, error) { var m Script scripts := [][]byte{scriptSig, scriptPubKey} m.scripts = make([][]parsedOpcode, len(scripts)) @@ -372,7 +371,6 @@ func NewScript(scriptSig []byte, scriptPubKey []byte, txidx int, tx *btcwire.Msg m.tx = *tx m.txidx = txidx - m.pver = pver m.condStack = []int{OpCondTrue} return &m, nil @@ -692,7 +690,7 @@ func (s *Script) calcScriptHash(script []parsedOpcode, hashType byte) []byte { } var wbuf bytes.Buffer - txCopy.BtcEncode(&wbuf, s.pver) + txCopy.Serialize(&wbuf) // Append LE 4 bytes hash type binary.Write(&wbuf, binary.LittleEndian, uint32(hashType)) diff --git a/script_test.go b/script_test.go index ac05927a..5f203792 100644 --- a/script_test.go +++ b/script_test.go @@ -1204,7 +1204,7 @@ var txTests = []txTest{ func testTx(t *testing.T, test txTest) { engine, err := btcscript.NewScript( test.tx.TxIn[test.idx].SignatureScript, test.pkScript, - test.idx, test.tx, 70001, test.bip16) + test.idx, test.tx, test.bip16) if err != nil { if err != test.parseErr { t.Errorf("Failed to parse %s: got \"%v\" expected "+ @@ -1731,7 +1731,7 @@ func TestBadPC(t *testing.T) { for _, test := range pcTests { engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript, - pkScript, 0, tx, 70001, false) + pkScript, 0, tx, false) if err != nil { t.Errorf("Failed to create script: %v", err) } @@ -1801,7 +1801,7 @@ func TestCheckErrorCondition(t *testing.T) { } engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript, pkScript, - 0, tx, 70001, false) + 0, tx, false) if err != nil { t.Errorf("failed to create script: %v", err) } From 17d37e3b060fd6d2693b40a189271a9e17cd814b Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Tue, 6 Aug 2013 18:00:05 +0100 Subject: [PATCH 039/174] Fix up some ErrorF strings in tests. One was missing a format directive. the others changed for consistency. Appeases go vet. --- opcode_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/opcode_test.go b/opcode_test.go index 61eb31c0..3f647e21 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -3896,16 +3896,16 @@ func testOpcode(t *testing.T, test *detailedTest) { if test.disassembly != "" { dis0, err := engine.DisasmScript(0) if err != nil { - t.Errorf("failed to disassemble script0 for %s: %v", + t.Errorf("%s: failed to disassemble script0: %v", test.name, err) } if dis0 != "" { - t.Errorf("disassembly of empty script gave \"%s\"", + t.Errorf("%s: disassembly of empty script gave \"%s\"", test.name, dis0) } disScript, err = engine.DisasmScript(1) if err != nil { - t.Errorf("failed to disassemble script for %s: %v", + t.Errorf("%s: failed to disassemble script: %v", test.name, err) } _, err = engine.DisasmScript(2) From 87e976a732988a9469d63ee0a64f65c767ae2993 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Wed, 25 Sep 2013 17:37:36 +0100 Subject: [PATCH 040/174] Add comment explaining OP_RESERVED behaviour with push ops. --- opcode.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/opcode.go b/opcode.go index 2edde0ae..ac7feef5 100644 --- a/opcode.go +++ b/opcode.go @@ -653,7 +653,8 @@ func (pop *parsedOpcode) conditional() bool { func (pop *parsedOpcode) exec(s *Script) error { // *sigh* bitcoind pretty much mandates that we violate layering here. // Any opcode that isn't just adding data to the stack counts here - // as an operation. + // as an operation. Note that OP_RESERVED is less than OP_16 and thus + // is counted as a push opcode here. if pop.opcode.value > OP_16 { s.numOps++ if s.numOps > MaxOpsPerScript { From a63edcd2dc3ef795712cf4422ee7dadc2bb99667 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Wed, 25 Sep 2013 17:38:20 +0100 Subject: [PATCH 041/174] preallocate a few arrays. When we do append loops, make an educated guess as to the size and make an array with that capacity to avoid extra copying. Doesn't affect the speed of the tests, over 4 runs the difference was lost in the noise. --- opcode.go | 16 ++++++++++------ script.go | 8 ++++---- test_coverage.txt | 10 +++++----- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/opcode.go b/opcode.go index ac7feef5..bb32eeb9 100644 --- a/opcode.go +++ b/opcode.go @@ -688,7 +688,15 @@ func (pop *parsedOpcode) print(oneline bool) string { } func (pop *parsedOpcode) bytes() []byte { - retbytes := []byte{pop.opcode.value} + var retbytes []byte + if pop.opcode.length > 0 { + retbytes = make([]byte, 1, pop.opcode.length) + } else { + retbytes = make([]byte, 1, 1 + len(pop.data) - + pop.opcode.length) + } + + retbytes[0] = pop.opcode.value if pop.opcode.length == 1 { return retbytes } @@ -708,11 +716,7 @@ func (pop *parsedOpcode) bytes() []byte { } } - for i := range pop.data { - retbytes = append(retbytes, pop.data[i]) - } - - return retbytes + return append(retbytes, pop.data...) } // opcode implementation functions from here diff --git a/script.go b/script.go index 581cf1eb..a74d19ef 100644 --- a/script.go +++ b/script.go @@ -274,7 +274,7 @@ func parseScript(script []byte) ([]parsedOpcode, error) { // template list for testing purposes. On error we return the list of parsed // opcodes so far. func parseScriptTemplate(script []byte, opcodemap map[byte]*opcode) ([]parsedOpcode, error) { - retScript := []parsedOpcode{} + retScript := make([]parsedOpcode, 0, len(script)) for i := 0; i < len(script); { instr := script[i] op, ok := opcodemap[instr] @@ -329,7 +329,7 @@ func parseScriptTemplate(script []byte, opcodemap map[byte]*opcode) ([]parsedOpc // unparseScript reversed the action of parseScript and returns the // parsedOpcodes as a list of bytes func unparseScript(pops []parsedOpcode) []byte { - script := []byte{} + script := make([]byte, 0, len(pops)) for _, pop := range pops { script = append(script, pop.bytes()...) } @@ -574,7 +574,7 @@ func (s *Script) subScript() []parsedOpcode { // removeOpcode will remove any opcode matching ``opcode'' from the opcode // stream in pkscript func removeOpcode(pkscript []parsedOpcode, opcode byte) []parsedOpcode { - retScript := []parsedOpcode{} + retScript := make([]parsedOpcode, 0, len(pkscript)) for _, pop := range pkscript { if pop.opcode.value != opcode { retScript = append(retScript, pop) @@ -586,7 +586,7 @@ func removeOpcode(pkscript []parsedOpcode, opcode byte) []parsedOpcode { // removeOpcodeByData will return the pkscript minus any opcodes that would // push the data in ``data'' to the stack. func removeOpcodeByData(pkscript []parsedOpcode, data []byte) []parsedOpcode { - retScript := []parsedOpcode{} + retScript := make([]parsedOpcode, 0, len(pkscript)) for _, pop := range pkscript { if !bytes.Equal(pop.data, data) { retScript = append(retScript, pop) diff --git a/test_coverage.txt b/test_coverage.txt index a9469f3e..84fc677d 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -2,13 +2,13 @@ github.com/conformal/btcscript/address.go scriptToAddressTemplate 100.00% (58/58) github.com/conformal/btcscript/script.go Script.Step 100.00% (37/37) github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (30/30) -github.com/conformal/btcscript/script.go NewScript 100.00% (19/19) +github.com/conformal/btcscript/script.go NewScript 100.00% (18/18) github.com/conformal/btcscript/stack.go asInt 100.00% (18/18) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) +github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (14/14) github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) -github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) -github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12) +github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) @@ -138,9 +138,9 @@ github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.21% (55/56) github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) github.com/conformal/btcscript/script.go Script.CheckErrorCondition 78.57% (11/14) github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) -github.com/conformal/btcscript/script.go Script.calcScriptHash 71.43% (25/35) +github.com/conformal/btcscript/script.go Script.calcScriptHash 64.10% (25/39) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 96.34% (896/930) +github.com/conformal/btcscript -------------------------- 95.94% (897/935) From 0a3e7f682b23aeb621e44617afcdf2c0d8fbd814 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Thu, 26 Sep 2013 01:53:11 +0100 Subject: [PATCH 042/174] Avoid the risk of leaking small amounts of memory. Removing from the bottom of a stack (nipN(depth)) would leak the first entry in the array by slicing [1:], leaving array[0] dangling an inaccessible (but unable to be freed until the whole slice is gone). We left it like this for a while, but best not to leak the memory. Happens rarely so the performance hit shouldn't matter that much. Do the same thing for condstack. --- opcode.go | 4 +++- stack.go | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/opcode.go b/opcode.go index bb32eeb9..2fcbd9fb 100644 --- a/opcode.go +++ b/opcode.go @@ -840,7 +840,9 @@ func opcodeEndif(op *parsedOpcode, s *Script) error { return StackErrNoIf } - s.condStack = s.condStack[1:] + stk := make([]int, len(s.condStack) -1, len(s.condStack) -1) + copy(stk, s.condStack[1:]) + s.condStack = stk return nil } diff --git a/stack.go b/stack.go index 952d5bdb..656c16a9 100644 --- a/stack.go +++ b/stack.go @@ -173,7 +173,9 @@ func (s *Stack) nipN(idx int) (so []byte, err error) { if idx == 0 { s.stk = s.stk[:sz-1] } else if idx == sz-1 { - s.stk = s.stk[1:] + s1 := make([][]byte, sz - 1, sz - 1) + copy(s1, s.stk[1:]) + s.stk = s1 } else { s1 := s.stk[sz-idx : sz] s.stk = s.stk[:sz-idx-1] From 29ed09cc98bbad0b71a6896c5845489152886a38 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 26 Sep 2013 20:34:25 -0500 Subject: [PATCH 043/174] Add IsPushOnlyScript. This commit adds an exported function, IsPushOnlyScript, which can be used to tell whether or not a script only pushes data (only contains opcodes that push data). --- script.go | 10 ++++++ test_coverage.txt | 85 ++++++++++++++++++++++++----------------------- 2 files changed, 53 insertions(+), 42 deletions(-) diff --git a/script.go b/script.go index a74d19ef..a4189637 100644 --- a/script.go +++ b/script.go @@ -236,6 +236,16 @@ func isPushOnly(pops []parsedOpcode) bool { return true } +// IsPushOnlyScript returns whether or not the passed script only pushes data. +// If the script does not parse false will be returned. +func IsPushOnlyScript(script []byte) bool { + pops, err := parseScript(script) + if err != nil { + return false + } + return isPushOnly(pops) +} + // GetScriptClass returns the class of the script passed. If the script does not // parse then NonStandardTy will be returned. func GetScriptClass(script []byte) ScriptClass { diff --git a/test_coverage.txt b/test_coverage.txt index 84fc677d..20a56830 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -4,75 +4,74 @@ github.com/conformal/btcscript/script.go Script.Step 100.00% (37/37) github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (30/30) github.com/conformal/btcscript/script.go NewScript 100.00% (18/18) github.com/conformal/btcscript/stack.go asInt 100.00% (18/18) +github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (14/14) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (14/14) -github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) -github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12) +github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) -github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) -github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) +github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) -github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) +github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) github.com/conformal/btcscript/script.go typeOfScript 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) -github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) +github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) github.com/conformal/btcscript/script.go unparseScript 100.00% (4/4) github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) @@ -80,46 +79,46 @@ github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) -github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) -github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) +github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) +github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) github.com/conformal/btcscript/script.go setStack 100.00% (3/3) -github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) +github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) +github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/conformal/btcscript/address.go ScriptToAddress 100.00% (2/2) +github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/conformal/btcscript/address.go ScriptToAddress 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) -github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) github.com/conformal/btcscript/opcode.go init 100.00% (1/1) github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/log.go init 100.00% (1/1) github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) +github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) @@ -127,13 +126,14 @@ github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) -github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) +github.com/conformal/btcscript/log.go init 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.21% (55/56) github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) github.com/conformal/btcscript/script.go Script.CheckErrorCondition 78.57% (11/14) @@ -141,6 +141,7 @@ github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) github.com/conformal/btcscript/script.go Script.calcScriptHash 64.10% (25/39) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) +github.com/conformal/btcscript/script.go IsPushOnlyScript 0.00% (0/4) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 95.94% (897/935) +github.com/conformal/btcscript -------------------------- 95.55% (901/943) From a5f81fc5457eec41c1438f12b0d92a27a586039f Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Tue, 10 Sep 2013 11:39:29 -0400 Subject: [PATCH 044/174] Add PayToPubKeyHashScript and SignatureScript functions. PayToPubKeyHashScript generates a new pay to pubkey hash script to use as the pkScript when creating new transactions. If the passed pubkey hash is an invalid size, StackErrInvalidOpcode will be returned as an error. SignatureScript returns the signature script necessary to validate a single input of a transaction. This also adds sanity checking for serializing scripts into byte slices. If the length of a serialized opcode does not equal the expected length, StackErrInvalidOpcode will be returned when unparsing a []parsedOpcode. New internal tests were added to verify checks for valid and invalid parsed opcodes. --- internal_test.go | 3668 ++++++++++++++++++++++++++++++++++++++++++++- opcode.go | 30 +- script.go | 144 +- script_test.go | 395 +++++ stack.go | 2 +- test_coverage.txt | 126 +- 6 files changed, 4278 insertions(+), 87 deletions(-) diff --git a/internal_test.go b/internal_test.go index d957ebb8..fb0d47d3 100644 --- a/internal_test.go +++ b/internal_test.go @@ -5,6 +5,9 @@ package btcscript import ( + "crypto/ecdsa" + "github.com/conformal/btcwire" + "io" "testing" ) @@ -17,7 +20,7 @@ func TstRemoveOpcode(pkscript []byte, opcode byte) ([]byte, error) { return nil, err } pops = removeOpcode(pops, opcode) - return unparseScript(pops), nil + return unparseScript(pops) } func TstRemoveOpcodeByData(pkscript []byte, data []byte) ([]byte, error) { @@ -26,7 +29,7 @@ func TstRemoveOpcodeByData(pkscript []byte, data []byte) ([]byte, error) { return nil, err } pops = removeOpcodeByData(pops, data) - return unparseScript(pops), nil + return unparseScript(pops) } // TestSetPC allows the test modules to set the program counter to whatever they @@ -36,6 +39,16 @@ func (s *Script) TstSetPC(script, off int) { s.scriptoff = off } +// TstSignatureScriptCustomReader allows the test modules to test the internal +// function signatureScriptCustomReader. +func TstSignatureScriptCustomReader(reader io.Reader, tx *btcwire.MsgTx, idx int, + subscript []byte, hashType byte, privkey *ecdsa.PrivateKey, + compress bool) ([]byte, error) { + + return signatureScriptCustomReader(reader, tx, idx, subscript, + hashType, privkey, compress) +} + // Tests for internal error cases in ScriptToAddress. // We pass bad format definitions to ScriptToAddrss to make sure the internal // checks work correctly. This is located in internal_test.go and not address.go @@ -117,3 +130,3654 @@ func TestParseOpcode(t *testing.T) { t.Errorf("no error with dodgy opcode map!") } } + +type popTest struct { + name string + pop *parsedOpcode + expectedErr error +} + +var popTests = []popTest{ + popTest{ + name: "OP_FALSE", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_FALSE], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_FALSE long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_FALSE], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_1 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_1], + data: nil, + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_1", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_1], + data: make([]byte, 1), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_1 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_1], + data: make([]byte, 2), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_2 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_2], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_2", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_2], + data: make([]byte, 2), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_2 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_2], + data: make([]byte, 3), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_3 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_3], + data: make([]byte, 2), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_3", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_3], + data: make([]byte, 3), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_3 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_3], + data: make([]byte, 4), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_4 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_4], + data: make([]byte, 3), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_4", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_4], + data: make([]byte, 4), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_4 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_4], + data: make([]byte, 5), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_5 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_5], + data: make([]byte, 4), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_5", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_5], + data: make([]byte, 5), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_5 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_5], + data: make([]byte, 6), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_6 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_6], + data: make([]byte, 5), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_6", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_6], + data: make([]byte, 6), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_6 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_6], + data: make([]byte, 7), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_7 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_7], + data: make([]byte, 6), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_7", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_7], + data: make([]byte, 7), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_7 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_7], + data: make([]byte, 8), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_8 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_8], + data: make([]byte, 7), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_8", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_8], + data: make([]byte, 8), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_8 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_8], + data: make([]byte, 9), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_9 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_9], + data: make([]byte, 8), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_9", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_9], + data: make([]byte, 9), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_9 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_9], + data: make([]byte, 10), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_10 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_10], + data: make([]byte, 9), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_10", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_10], + data: make([]byte, 10), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_10 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_10], + data: make([]byte, 11), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_11 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_11], + data: make([]byte, 10), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_11", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_11], + data: make([]byte, 11), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_11 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_11], + data: make([]byte, 12), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_12 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_12], + data: make([]byte, 11), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_12", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_12], + data: make([]byte, 12), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_12 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_12], + data: make([]byte, 13), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_13 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_13], + data: make([]byte, 12), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_13", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_13], + data: make([]byte, 13), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_13 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_13], + data: make([]byte, 14), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_14 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_14], + data: make([]byte, 13), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_14", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_14], + data: make([]byte, 14), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_14 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_14], + data: make([]byte, 15), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_15 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_15], + data: make([]byte, 14), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_15", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_15], + data: make([]byte, 15), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_15 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_15], + data: make([]byte, 16), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_16 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_16], + data: make([]byte, 15), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_16", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_16], + data: make([]byte, 16), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_16 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_16], + data: make([]byte, 17), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_17 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_17], + data: make([]byte, 16), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_17", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_17], + data: make([]byte, 17), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_17 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_17], + data: make([]byte, 18), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_18 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_18], + data: make([]byte, 17), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_18", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_18], + data: make([]byte, 18), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_18 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_18], + data: make([]byte, 19), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_19 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_19], + data: make([]byte, 18), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_19", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_19], + data: make([]byte, 19), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_19 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_19], + data: make([]byte, 20), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_20 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_20], + data: make([]byte, 19), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_20", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_20], + data: make([]byte, 20), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_20 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_20], + data: make([]byte, 21), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_21 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_21], + data: make([]byte, 20), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_21", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_21], + data: make([]byte, 21), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_21 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_21], + data: make([]byte, 22), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_22 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_22], + data: make([]byte, 21), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_22", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_22], + data: make([]byte, 22), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_22 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_22], + data: make([]byte, 23), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_23 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_23], + data: make([]byte, 22), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_23", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_23], + data: make([]byte, 23), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_23 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_23], + data: make([]byte, 24), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_24 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_24], + data: make([]byte, 23), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_24", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_24], + data: make([]byte, 24), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_24 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_24], + data: make([]byte, 25), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_25 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_25], + data: make([]byte, 24), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_25", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_25], + data: make([]byte, 25), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_25 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_25], + data: make([]byte, 26), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_26 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_26], + data: make([]byte, 25), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_26", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_26], + data: make([]byte, 26), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_26 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_26], + data: make([]byte, 27), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_27 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_27], + data: make([]byte, 26), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_27", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_27], + data: make([]byte, 27), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_27 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_27], + data: make([]byte, 28), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_28 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_28], + data: make([]byte, 27), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_28", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_28], + data: make([]byte, 28), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_28 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_28], + data: make([]byte, 29), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_29 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_29], + data: make([]byte, 28), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_29", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_29], + data: make([]byte, 29), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_29 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_29], + data: make([]byte, 30), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_30 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_30], + data: make([]byte, 29), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_30", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_30], + data: make([]byte, 30), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_30 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_30], + data: make([]byte, 31), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_31 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_31], + data: make([]byte, 30), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_31", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_31], + data: make([]byte, 31), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_31 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_31], + data: make([]byte, 32), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_32 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_32], + data: make([]byte, 31), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_32", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_32], + data: make([]byte, 32), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_32 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_32], + data: make([]byte, 33), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_33 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_33], + data: make([]byte, 32), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_33", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_33], + data: make([]byte, 33), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_33 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_33], + data: make([]byte, 34), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_34 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_34], + data: make([]byte, 33), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_34", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_34], + data: make([]byte, 34), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_34 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_34], + data: make([]byte, 35), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_35 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_35], + data: make([]byte, 34), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_35", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_35], + data: make([]byte, 35), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_35 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_35], + data: make([]byte, 36), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_36 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_36], + data: make([]byte, 35), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_36", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_36], + data: make([]byte, 36), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_36 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_36], + data: make([]byte, 37), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_37 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_37], + data: make([]byte, 36), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_37", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_37], + data: make([]byte, 37), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_37 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_37], + data: make([]byte, 38), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_38 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_38], + data: make([]byte, 37), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_38", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_38], + data: make([]byte, 38), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_38 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_38], + data: make([]byte, 39), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_39 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_39], + data: make([]byte, 38), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_39", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_39], + data: make([]byte, 39), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_39 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_39], + data: make([]byte, 40), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_40 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_40], + data: make([]byte, 39), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_40", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_40], + data: make([]byte, 40), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_40 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_40], + data: make([]byte, 41), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_41 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_41], + data: make([]byte, 40), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_41", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_41], + data: make([]byte, 41), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_41 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_41], + data: make([]byte, 42), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_42 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_42], + data: make([]byte, 41), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_42", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_42], + data: make([]byte, 42), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_42 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_42], + data: make([]byte, 43), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_43 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_43], + data: make([]byte, 42), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_43", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_43], + data: make([]byte, 43), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_43 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_43], + data: make([]byte, 44), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_44 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_44], + data: make([]byte, 43), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_44", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_44], + data: make([]byte, 44), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_44 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_44], + data: make([]byte, 45), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_45 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_45], + data: make([]byte, 44), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_45", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_45], + data: make([]byte, 45), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_45 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_45], + data: make([]byte, 46), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_46 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_46], + data: make([]byte, 45), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_46", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_46], + data: make([]byte, 46), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_46 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_46], + data: make([]byte, 47), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_47 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_47], + data: make([]byte, 46), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_47", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_47], + data: make([]byte, 47), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_47 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_47], + data: make([]byte, 48), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_48 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_48], + data: make([]byte, 47), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_48", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_48], + data: make([]byte, 48), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_48 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_48], + data: make([]byte, 49), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_49 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_49], + data: make([]byte, 48), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_49", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_49], + data: make([]byte, 49), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_49 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_49], + data: make([]byte, 50), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_50 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_50], + data: make([]byte, 49), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_50", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_50], + data: make([]byte, 50), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_50 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_50], + data: make([]byte, 51), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_51 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_51], + data: make([]byte, 50), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_51", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_51], + data: make([]byte, 51), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_51 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_51], + data: make([]byte, 52), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_52 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_52], + data: make([]byte, 51), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_52", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_52], + data: make([]byte, 52), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_52 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_52], + data: make([]byte, 53), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_53 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_53], + data: make([]byte, 52), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_53", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_53], + data: make([]byte, 53), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_53 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_53], + data: make([]byte, 54), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_54 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_54], + data: make([]byte, 53), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_54", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_54], + data: make([]byte, 54), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_54 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_54], + data: make([]byte, 55), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_55 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_55], + data: make([]byte, 54), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_55", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_55], + data: make([]byte, 55), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_55 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_55], + data: make([]byte, 56), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_56 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_56], + data: make([]byte, 55), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_56", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_56], + data: make([]byte, 56), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_56 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_56], + data: make([]byte, 57), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_57 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_57], + data: make([]byte, 56), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_57", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_57], + data: make([]byte, 57), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_57 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_57], + data: make([]byte, 58), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_58 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_58], + data: make([]byte, 57), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_58", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_58], + data: make([]byte, 58), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_58 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_58], + data: make([]byte, 59), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_59 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_59], + data: make([]byte, 58), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_59", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_59], + data: make([]byte, 59), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_59 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_59], + data: make([]byte, 60), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_60 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_60], + data: make([]byte, 59), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_60", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_60], + data: make([]byte, 60), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_60 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_60], + data: make([]byte, 61), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_61 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_61], + data: make([]byte, 60), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_61", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_61], + data: make([]byte, 61), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_61 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_61], + data: make([]byte, 62), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_62 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_62], + data: make([]byte, 61), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_62", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_62], + data: make([]byte, 62), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_62 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_62], + data: make([]byte, 63), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_63 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_63], + data: make([]byte, 62), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_63", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_63], + data: make([]byte, 63), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_63 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_63], + data: make([]byte, 64), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_64 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_64], + data: make([]byte, 63), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_64", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_64], + data: make([]byte, 64), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_64 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_64], + data: make([]byte, 65), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_65 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_65], + data: make([]byte, 64), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_65", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_65], + data: make([]byte, 65), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_65 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_65], + data: make([]byte, 66), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_66 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_66], + data: make([]byte, 65), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_66", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_66], + data: make([]byte, 66), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_66 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_66], + data: make([]byte, 67), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_67 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_67], + data: make([]byte, 66), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_67", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_67], + data: make([]byte, 67), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_67 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_67], + data: make([]byte, 68), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_68 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_68], + data: make([]byte, 67), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_68", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_68], + data: make([]byte, 68), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_68 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_68], + data: make([]byte, 69), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_69 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_69], + data: make([]byte, 68), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_69", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_69], + data: make([]byte, 69), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_69 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_69], + data: make([]byte, 70), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_70 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_70], + data: make([]byte, 69), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_70", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_70], + data: make([]byte, 70), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_70 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_70], + data: make([]byte, 71), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_71 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_71], + data: make([]byte, 70), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_71", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_71], + data: make([]byte, 71), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_71 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_71], + data: make([]byte, 72), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_72 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_72], + data: make([]byte, 71), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_72", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_72], + data: make([]byte, 72), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_72 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_72], + data: make([]byte, 73), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_73 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_73], + data: make([]byte, 72), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_73", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_73], + data: make([]byte, 73), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_73 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_73], + data: make([]byte, 74), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_74 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_74], + data: make([]byte, 73), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_74", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_74], + data: make([]byte, 74), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_74 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_74], + data: make([]byte, 75), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_75 short", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_75], + data: make([]byte, 74), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DATA_75", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_75], + data: make([]byte, 75), + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DATA_75 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DATA_75], + data: make([]byte, 76), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_PUSHDATA1", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_PUSHDATA1], + data: []byte{0, 1, 2, 3, 4}, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_PUSHDATA2", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_PUSHDATA2], + data: []byte{0, 1, 2, 3, 4}, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_PUSHDATA4", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_PUSHDATA1], + data: []byte{0, 1, 2, 3, 4}, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_1NEGATE", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_1NEGATE], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_1NEGATE long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_1NEGATE], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_RESERVED", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_RESERVED], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_RESERVED long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_RESERVED], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_TRUE", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_TRUE], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_TRUE long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_TRUE], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_2", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_2], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_2 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_2], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_2", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_2], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_2 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_2], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_3", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_3], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_3 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_3], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_4", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_4], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_4 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_4], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_5", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_5], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_5 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_5], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_6", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_6], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_6 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_6], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_7", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_7], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_7 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_7], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_8", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_8], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_8 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_8], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_9", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_9], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_9 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_9], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_10", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_10], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_10 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_10], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_11", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_11], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_11 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_11], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_12", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_12], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_12 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_12], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_13", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_13], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_13 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_13], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_14", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_14], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_14 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_14], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_15", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_15], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_15 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_15], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_16", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_16], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_16 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_16], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_NOP", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOP], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_NOP long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOP], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_VER", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_VER], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_VER long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_VER], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_IF", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_IF], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_IF long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_IF], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_NOTIF", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOTIF], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_NOTIF long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOTIF], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_VERIF", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_VERIF], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_VERIF long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_VERIF], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_VERNOTIF", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_VERNOTIF], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_VERNOTIF long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_VERNOTIF], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_ELSE", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_ELSE], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_ELSE long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_ELSE], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_ENDIF", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_ENDIF], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_ENDIF long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_ENDIF], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_VERIFY", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_VERIFY], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_VERIFY long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_VERIFY], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_RETURN", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_RETURN], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_RETURN long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_RETURN], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_TOALTSTACK", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_TOALTSTACK], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_TOALTSTACK long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_TOALTSTACK], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_FROMALTSTACK", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_FROMALTSTACK], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_FROMALTSTACK long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_FROMALTSTACK], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_2DROP", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_2DROP], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_2DROP long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_2DROP], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_2DUP", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_2DUP], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_2DUP long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_2DUP], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_3DUP", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_3DUP], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_3DUP long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_3DUP], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_2OVER", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_2OVER], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_2OVER long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_2OVER], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_2ROT", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_2ROT], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_2ROT long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_2ROT], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_2SWAP", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_2SWAP], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_2SWAP long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_2SWAP], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_IFDUP", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_IFDUP], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_IFDUP long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_IFDUP], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DEPTH", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DEPTH], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DEPTH long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DEPTH], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DROP", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DROP], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DROP long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DROP], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DUP", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DUP], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DUP long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DUP], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_NIP", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NIP], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_NIP long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NIP], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_OVER", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_OVER], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_OVER long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_OVER], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_PICK", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_PICK], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_PICK long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_PICK], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_ROLL", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_ROLL], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_ROLL long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_ROLL], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_ROT", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_ROT], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_ROT long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_ROT], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_SWAP", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_SWAP], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_SWAP long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_SWAP], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_TUCK", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_TUCK], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_TUCK long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_TUCK], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_CAT", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_CAT], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_CAT long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_CAT], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_SUBSTR", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_SUBSTR], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_SUBSTR long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_SUBSTR], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_LEFT", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_LEFT], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_LEFT long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_LEFT], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_LEFT", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_LEFT], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_LEFT long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_LEFT], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_RIGHT", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_RIGHT], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_RIGHT long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_RIGHT], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_SIZE", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_SIZE], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_SIZE long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_SIZE], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_INVERT", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_INVERT], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_INVERT long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_INVERT], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_AND", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_AND], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_AND long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_AND], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_OR", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_OR], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_OR long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_OR], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_XOR", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_XOR], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_XOR long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_XOR], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_EQUAL", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_EQUAL], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_EQUAL long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_EQUAL], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_EQUALVERIFY", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_EQUALVERIFY], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_EQUALVERIFY long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_EQUALVERIFY], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_RESERVED1", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_RESERVED1], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_RESERVED1 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_RESERVED1], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_RESERVED2", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_RESERVED2], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_RESERVED2 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_RESERVED2], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_1ADD", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_1ADD], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_1ADD long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_1ADD], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_1SUB", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_1SUB], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_1SUB long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_1SUB], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_2MUL", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_2MUL], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_2MUL long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_2MUL], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_2DIV", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_2DIV], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_2DIV long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_2DIV], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_NEGATE", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NEGATE], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_NEGATE long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NEGATE], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_ABS", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_ABS], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_ABS long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_ABS], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_NOT", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOT], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_NOT long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOT], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_0NOTEQUAL", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_0NOTEQUAL], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_0NOTEQUAL long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_0NOTEQUAL], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_ADD", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_ADD], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_ADD long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_ADD], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_SUB", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_SUB], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_SUB long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_SUB], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_MUL", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_MUL], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_MUL long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_MUL], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_DIV", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DIV], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_DIV long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_DIV], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_MOD", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_MOD], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_MOD long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_MOD], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_LSHIFT", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_LSHIFT], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_LSHIFT long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_LSHIFT], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_RSHIFT", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_RSHIFT], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_RSHIFT long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_RSHIFT], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_BOOLAND", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_BOOLAND], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_BOOLAND long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_BOOLAND], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_BOOLOR", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_BOOLOR], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_BOOLOR long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_BOOLOR], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_NUMEQUAL", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NUMEQUAL], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_NUMEQUAL long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NUMEQUAL], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_NUMEQUALVERIFY", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NUMEQUALVERIFY], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_NUMEQUALVERIFY long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NUMEQUALVERIFY], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_NUMNOTEQUAL", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NUMNOTEQUAL], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_NUMNOTEQUAL long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NUMNOTEQUAL], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_LESSTHAN", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_LESSTHAN], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_LESSTHAN long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_LESSTHAN], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_GREATERTHAN", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_GREATERTHAN], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_GREATERTHAN long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_GREATERTHAN], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_LESSTHANOREQUAL", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_LESSTHANOREQUAL], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_LESSTHANOREQUAL long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_LESSTHANOREQUAL], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_GREATERTHANOREQUAL", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_GREATERTHANOREQUAL], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_GREATERTHANOREQUAL long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_GREATERTHANOREQUAL], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_MIN", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_MIN], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_MIN long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_MIN], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_MAX", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_MAX], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_MAX long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_MAX], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_WITHIN", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_WITHIN], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_WITHIN long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_WITHIN], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_RIPEMD160", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_RIPEMD160], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_RIPEMD160 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_RIPEMD160], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_SHA1", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_SHA1], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_SHA1 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_SHA1], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_SHA256", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_SHA256], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_SHA256 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_SHA256], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_HASH160", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_HASH160], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_HASH160 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_HASH160], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_HASH256", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_HASH256], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_HASH256 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_HASH256], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_CODESAPERATOR", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_CODESEPARATOR], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_CODESEPARATOR long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_CODESEPARATOR], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_CHECKSIG", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_CHECKSIG], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_CHECKSIG long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_CHECKSIG], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_CHECKSIGVERIFY", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_CHECKSIGVERIFY], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_CHECKSIGVERIFY long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_CHECKSIGVERIFY], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_CHECK_MULTISIG", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_CHECK_MULTISIG], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_CHECK_MULTISIG long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_CHECK_MULTISIG], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_CHECKMULTISIGVERIFY", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_CHECKMULTISIGVERIFY], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_CHECKMULTISIGVERIFY long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_CHECKMULTISIGVERIFY], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_NOP1", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOP1], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_NOP1 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOP1], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_NOP2", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOP2], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_NOP2 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOP2], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_NOP3", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOP3], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_NOP3 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOP3], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_NOP4", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOP4], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_NOP4 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOP4], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_NOP5", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOP5], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_NOP5 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOP5], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_NOP6", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOP6], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_NOP6 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOP6], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_NOP7", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOP7], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_NOP7 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOP7], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_NOP8", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOP8], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_NOP8 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOP8], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_NOP9", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOP9], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_NOP9 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOP9], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_NOP10", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOP10], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_NOP10 long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_NOP10], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_PUBKEYHASH", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_PUBKEYHASH], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_PUBKEYHASH long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_PUBKEYHASH], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_PUBKEY", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_PUBKEY], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_PUBKEY long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_PUBKEY], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, + popTest{ + name: "OP_INVALIDOPCODE", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_INVALIDOPCODE], + data: nil, + }, + expectedErr: nil, + }, + popTest{ + name: "OP_INVALIDOPCODE long", + pop: &parsedOpcode{ + opcode: opcodemapPreinit[OP_INVALIDOPCODE], + data: make([]byte, 1), + }, + expectedErr: StackErrInvalidOpcode, + }, +} + +func TestUnparsingInvalidOpcodes(t *testing.T) { + for _, test := range popTests { + _, err := test.pop.bytes() + if err != test.expectedErr { + t.Errorf("Parsed Opcode test '%s' failed", test.name) + t.Error(err, test.expectedErr) + } + } +} diff --git a/opcode.go b/opcode.go index 2fcbd9fb..83c496f3 100644 --- a/opcode.go +++ b/opcode.go @@ -10,6 +10,7 @@ import ( "crypto/ecdsa" "crypto/sha1" "crypto/sha256" + "encoding/binary" "fmt" "github.com/conformal/btcec" "github.com/conformal/btcwire" @@ -687,36 +688,51 @@ func (pop *parsedOpcode) print(oneline bool) string { return retString } -func (pop *parsedOpcode) bytes() []byte { +func (pop *parsedOpcode) bytes() ([]byte, error) { var retbytes []byte if pop.opcode.length > 0 { retbytes = make([]byte, 1, pop.opcode.length) } else { - retbytes = make([]byte, 1, 1 + len(pop.data) - + retbytes = make([]byte, 1, 1+len(pop.data)- pop.opcode.length) } retbytes[0] = pop.opcode.value if pop.opcode.length == 1 { - return retbytes + if len(pop.data) != 0 { + return nil, StackErrInvalidOpcode + } + return retbytes, nil } + nbytes := pop.opcode.length if pop.opcode.length < 0 { l := len(pop.data) // tempting just to hardcode to avoid the complexity here. switch pop.opcode.length { case -1: retbytes = append(retbytes, byte(l)) + nbytes = int(retbytes[1]) + len(retbytes) case -2: retbytes = append(retbytes, byte(l&0xff), byte(l>>8&0xff)) + nbytes = int(binary.LittleEndian.Uint16(retbytes[1:])) + + len(retbytes) case -4: retbytes = append(retbytes, byte(l&0xff), byte((l>>8)&0xff), byte((l>>16)&0xff), byte((l>>24)&0xff)) + nbytes = int(binary.LittleEndian.Uint32(retbytes[1:])) + + len(retbytes) } } - return append(retbytes, pop.data...) + retbytes = append(retbytes, pop.data...) + + if len(retbytes) != nbytes { + return nil, StackErrInvalidOpcode + } + + return retbytes, nil } // opcode implementation functions from here @@ -840,7 +856,7 @@ func opcodeEndif(op *parsedOpcode, s *Script) error { return StackErrNoIf } - stk := make([]int, len(s.condStack) -1, len(s.condStack) -1) + stk := make([]int, len(s.condStack)-1, len(s.condStack)-1) copy(stk, s.condStack[1:]) s.condStack = stk return nil @@ -1457,7 +1473,7 @@ func opcodeCheckSig(op *parsedOpcode, s *Script) error { // the script if present. subScript = removeOpcodeByData(subScript, sigStr) - hash := s.calcScriptHash(subScript, hashType) + hash := calcScriptHash(subScript, hashType, &s.tx, s.txidx) pubKey, err := btcec.ParsePubKey(pkStr, btcec.S256()) if err != nil { @@ -1576,7 +1592,7 @@ func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error { // get hashtype from original byte string hashType := sigStrings[i][len(sigStrings[i])-1] - hash := s.calcScriptHash(script, hashType) + hash := calcScriptHash(script, hashType, &s.tx, s.txidx) inner: // Find first pubkey that successfully validates signature. // we start off the search from the key that was successful diff --git a/script.go b/script.go index a4189637..86ae9198 100644 --- a/script.go +++ b/script.go @@ -6,11 +6,16 @@ package btcscript import ( "bytes" + "crypto/ecdsa" + "crypto/rand" "encoding/binary" "errors" "fmt" + "github.com/conformal/btcec" "github.com/conformal/btcwire" "github.com/davecgh/go-spew/spew" + "io" + "math/big" "time" ) @@ -338,12 +343,16 @@ func parseScriptTemplate(script []byte, opcodemap map[byte]*opcode) ([]parsedOpc // unparseScript reversed the action of parseScript and returns the // parsedOpcodes as a list of bytes -func unparseScript(pops []parsedOpcode) []byte { +func unparseScript(pops []parsedOpcode) ([]byte, error) { script := make([]byte, 0, len(pops)) for _, pop := range pops { - script = append(script, pop.bytes()...) + b, err := pop.bytes() + if err != nil { + return nil, err + } + script = append(script, b...) } - return script + return script, nil } // NewScript returns a new script engine for the provided tx and input idx with @@ -625,22 +634,23 @@ func DisasmString(buf []byte) (string, error) { // calcScriptHash will, given the a script and hashtype for the current // scriptmachine, calculate the doubleSha256 hash of the transaction and // script to be used for signature signing and verification. -func (s *Script) calcScriptHash(script []parsedOpcode, hashType byte) []byte { +func calcScriptHash(script []parsedOpcode, hashType byte, tx *btcwire.MsgTx, idx int) []byte { // remove all instances of OP_CODESEPARATOR still left in the script script = removeOpcode(script, OP_CODESEPARATOR) // Make a deep copy of the transaction, zeroing out the script // for all inputs that are not currently being processed. - txCopy := s.tx.Copy() - txidx := s.txidx + txCopy := tx.Copy() for i := range txCopy.TxIn { var txIn btcwire.TxIn txIn = *txCopy.TxIn[i] txCopy.TxIn[i] = &txIn - if i == txidx { - txCopy.TxIn[txidx].SignatureScript = - unparseScript(script) + if i == idx { + // unparseScript cannot fail here, because removeOpcode + // above only returns a valid script. + sigscript, _ := unparseScript(script) + txCopy.TxIn[idx].SignatureScript = sigscript } else { txCopy.TxIn[i].SignatureScript = []byte{} } @@ -656,12 +666,12 @@ func (s *Script) calcScriptHash(script []parsedOpcode, hashType byte) []byte { case SigHashNone: txCopy.TxOut = txCopy.TxOut[0:0] // empty slice for i := range txCopy.TxIn { - if i != txidx { + if i != idx { txCopy.TxIn[i].Sequence = 0 } } case SigHashSingle: - if txidx >= len(txCopy.TxOut) { + if idx >= len(txCopy.TxOut) { // This was created by a buggy implementation. // In this case we do the same as bitcoind and bitcoinj // and return 1 (as a uint256 little endian) as an @@ -673,15 +683,15 @@ func (s *Script) calcScriptHash(script []parsedOpcode, hashType byte) []byte { return hash } // Resize output array to up to and including requested index. - txCopy.TxOut = txCopy.TxOut[:txidx+1] + txCopy.TxOut = txCopy.TxOut[:idx+1] // all but current output get zeroed out - for i := 0; i < txidx; i++ { + for i := 0; i < idx; i++ { txCopy.TxOut[i].Value = -1 txCopy.TxOut[i].PkScript = []byte{} } // Sequence on all other inputs is 0, too. for i := range txCopy.TxIn { - if i != txidx { + if i != idx { txCopy.TxIn[i].Sequence = 0 } } @@ -695,8 +705,8 @@ func (s *Script) calcScriptHash(script []parsedOpcode, hashType byte) []byte { // nothing special here } if hashType&SigHashAnyOneCanPay != 0 { - txCopy.TxIn = txCopy.TxIn[s.txidx : s.txidx+1] - txidx = 0 + txCopy.TxIn = txCopy.TxIn[idx : idx+1] + idx = 0 } var wbuf bytes.Buffer @@ -861,3 +871,105 @@ func getSigOpCount(pops []parsedOpcode, precise bool) int { return nSigs } + +// PayToPubKeyHashScript creates a new script to pay a transaction +// output to a 20-byte pubkey hash. +func PayToPubKeyHashScript(pubKeyHash []byte) (pkScript []byte, err error) { + pops := []parsedOpcode{ + parsedOpcode{ + opcode: opcodemap[OP_DUP], + }, + parsedOpcode{ + opcode: opcodemap[OP_HASH160], + }, + parsedOpcode{ + opcode: opcodemap[OP_DATA_20], + data: pubKeyHash, + }, + parsedOpcode{ + opcode: opcodemap[OP_EQUALVERIFY], + }, + parsedOpcode{ + opcode: opcodemap[OP_CHECKSIG], + }, + } + return unparseScript(pops) +} + +// SignatureScript creates an input signature script for tx to spend +// BTC sent from a previous output to the owner of privkey. tx must +// include all transaction inputs and outputs, however txin scripts are +// allowed to be filled or empty. The returned script is calculated to +// be used as the idx'th txin sigscript for tx. subscript is the PkScript +// of the previous output being used as the idx'th input. privkey is +// serialized in either a compressed or uncompressed format based on +// compress. This format must match the same format used to generate +// the payment address, or the script validation will fail. +func SignatureScript(tx *btcwire.MsgTx, idx int, subscript []byte, hashType byte, privkey *ecdsa.PrivateKey, compress bool) ([]byte, error) { + + return signatureScriptCustomReader(rand.Reader, tx, idx, subscript, + hashType, privkey, compress) +} + +// This function exists so we can test ecdsa.Sign's error for an invalid +// reader. +func signatureScriptCustomReader(reader io.Reader, tx *btcwire.MsgTx, idx int, + subscript []byte, hashType byte, privkey *ecdsa.PrivateKey, + compress bool) ([]byte, error) { + + parsedScript, err := parseScript(subscript) + if err != nil { + return nil, fmt.Errorf("cannot parse output script: %v", err) + } + hash := calcScriptHash(parsedScript, hashType, tx, idx) + r, s, err := ecdsa.Sign(reader, privkey, hash) + if err != nil { + return nil, fmt.Errorf("cannot sign tx input: %s", err) + } + sig := append(sigDER(r, s), hashType) + + pk := (*btcec.PublicKey)(&privkey.PublicKey) + var pubkeyOpcode *parsedOpcode + if compress { + pubkeyOpcode = &parsedOpcode{ + opcode: opcodemap[OP_DATA_33], + data: pk.SerializeCompressed(), + } + } else { + pubkeyOpcode = &parsedOpcode{ + opcode: opcodemap[OP_DATA_65], + data: pk.SerializeUncompressed(), + } + } + pops := []parsedOpcode{ + parsedOpcode{ + opcode: opcodemap[byte(len(sig))], + data: sig, + }, + *pubkeyOpcode, + } + return unparseScript(pops) +} + +// sigDER returns the ECDSA signature r, s in the DER format used by +// signature scripts. The signature does not include the appended hashtype. +// +// encoding/asn1 is broken so we hand roll this output: +// +// 0x30 0x02 r 0x02 s +func sigDER(r, s *big.Int) []byte { + // total length of returned signature is 1 byte for each magic and + // length (6 total), plus lengths of r and s + length := 6 + len(r.Bytes()) + len(s.Bytes()) + b := make([]byte, length, length) + + b[0] = 0x30 + b[1] = byte(length - 2) + b[2] = 0x02 + b[3] = byte(len(r.Bytes())) + offset := copy(b[4:], r.Bytes()) + 4 + b[offset] = 0x02 + b[offset+1] = byte(len(s.Bytes())) + copy(b[offset+2:], s.Bytes()) + return b +} diff --git a/script_test.go b/script_test.go index 5f203792..951ef851 100644 --- a/script_test.go +++ b/script_test.go @@ -6,8 +6,11 @@ package btcscript_test import ( "bytes" + "crypto/ecdsa" + "github.com/conformal/btcec" "github.com/conformal/btcscript" "github.com/conformal/btcwire" + "math/big" "testing" ) @@ -1839,3 +1842,395 @@ func TestCheckErrorCondition(t *testing.T) { t.Errorf("unexpected error %v on final check", err) } } + +func TestPayToPubKeyHashScript(t *testing.T) { + validaddr := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20} + invalidaddr := validaddr[:len(validaddr)-2] + + expected := []byte{btcscript.OP_DUP, btcscript.OP_HASH160, + btcscript.OP_DATA_20, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, btcscript.OP_EQUALVERIFY, + btcscript.OP_CHECKSIG} + + script, err := btcscript.PayToPubKeyHashScript(validaddr) + if err != nil { + t.Error(err) + return + } + if !bytes.Equal(script, expected) { + t.Error("Unexpected script result.") + return + } + + _, err = btcscript.PayToPubKeyHashScript(invalidaddr) + if err == nil { + t.Error("Erroneously created script for invalid address.") + return + } +} + +type TstSigScript struct { + name string + inputs []TstInput + hashtype byte + compress bool + scriptAtWrongIndex bool +} + +type TstInput struct { + txout *btcwire.TxOut + sigscriptGenerates bool + inputValidates bool + indexOutOfRange bool + invalidReader bool +} + +var coinbaseOutPoint = &btcwire.OutPoint{ + Index: (1 << 32) - 1, +} + +// Pregenerated private key, with associated public key and pkScripts +// for the uncompressed and compressed hash160. +var ( + privkeyD = []byte{0x6b, 0x0f, 0xd8, 0xda, 0x54, 0x22, 0xd0, 0xb7, + 0xb4, 0xfc, 0x4e, 0x55, 0xd4, 0x88, 0x42, 0xb3, 0xa1, 0x65, + 0xac, 0x70, 0x7f, 0x3d, 0xa4, 0x39, 0x5e, 0xcb, 0x3b, 0xb0, + 0xd6, 0x0e, 0x06, 0x92} + pubkeyX = []byte{0xb2, 0x52, 0xf0, 0x49, 0x85, 0x78, 0x03, 0x03, 0xc8, + 0x7d, 0xce, 0x51, 0x7f, 0xa8, 0x69, 0x0b, 0x91, 0x95, 0xf4, + 0xf3, 0x5c, 0x26, 0x73, 0x05, 0x05, 0xa2, 0xee, 0xbc, 0x09, + 0x38, 0x34, 0x3a} + pubkeyY = []byte{0xb7, 0xc6, 0x7d, 0xb2, 0xe1, 0xff, 0xc8, 0x43, 0x1f, + 0x63, 0x32, 0x62, 0xaa, 0x60, 0xc6, 0x83, 0x30, 0xbd, 0x24, + 0x7e, 0xef, 0xdb, 0x6f, 0x2e, 0x8d, 0x56, 0xf0, 0x3c, 0x9f, + 0x6d, 0xb6, 0xf8} + uncompressedPkScript = []byte{0x76, 0xa9, 0x14, 0xd1, 0x7c, 0xb5, + 0xeb, 0xa4, 0x02, 0xcb, 0x68, 0xe0, 0x69, 0x56, 0xbf, 0x32, + 0x53, 0x90, 0x0e, 0x0a, 0x86, 0xc9, 0xfa, 0x88, 0xac} + compressedPkScript = []byte{0x76, 0xa9, 0x14, 0x27, 0x4d, 0x9f, 0x7f, + 0x61, 0x7e, 0x7c, 0x7a, 0x1c, 0x1f, 0xb2, 0x75, 0x79, 0x10, + 0x43, 0x65, 0x68, 0x27, 0x9d, 0x86, 0x88, 0xac} + shortPkScript = []byte{0x76, 0xa9, 0x14, 0xd1, 0x7c, 0xb5, + 0xeb, 0xa4, 0x02, 0xcb, 0x68, 0xe0, 0x69, 0x56, 0xbf, 0x32, + 0x53, 0x90, 0x0e, 0x0a, 0x88, 0xac} + uncompressedAddrStr = "1L6fd93zGmtzkK6CsZFVVoCwzZV3MUtJ4F" + compressedAddrStr = "14apLppt9zTq6cNw8SDfiJhk9PhkZrQtYZ" +) + +// Pretend output amounts. +const coinbaseVal = 2500000000 +const fee = 5000000 + +var SigScriptTests = []TstSigScript{ + TstSigScript{ + name: "one input uncompressed", + inputs: []TstInput{ + TstInput{ + txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), + sigscriptGenerates: true, + inputValidates: true, + indexOutOfRange: false, + }, + }, + hashtype: btcscript.SigHashAll, + compress: false, + scriptAtWrongIndex: false, + }, + TstSigScript{ + name: "two inputs uncompressed", + inputs: []TstInput{ + TstInput{ + txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), + sigscriptGenerates: true, + inputValidates: true, + indexOutOfRange: false, + }, + TstInput{ + txout: btcwire.NewTxOut(coinbaseVal+fee, uncompressedPkScript), + sigscriptGenerates: true, + inputValidates: true, + indexOutOfRange: false, + }, + }, + hashtype: btcscript.SigHashAll, + compress: false, + scriptAtWrongIndex: false, + }, + TstSigScript{ + name: "one input compressed", + inputs: []TstInput{ + TstInput{ + txout: btcwire.NewTxOut(coinbaseVal, compressedPkScript), + sigscriptGenerates: true, + inputValidates: true, + indexOutOfRange: false, + }, + }, + hashtype: btcscript.SigHashAll, + compress: true, + scriptAtWrongIndex: false, + }, + TstSigScript{ + name: "two inputs compressed", + inputs: []TstInput{ + TstInput{ + txout: btcwire.NewTxOut(coinbaseVal, compressedPkScript), + sigscriptGenerates: true, + inputValidates: true, + indexOutOfRange: false, + }, + TstInput{ + txout: btcwire.NewTxOut(coinbaseVal+fee, compressedPkScript), + sigscriptGenerates: true, + inputValidates: true, + indexOutOfRange: false, + }, + }, + hashtype: btcscript.SigHashAll, + compress: true, + scriptAtWrongIndex: false, + }, + TstSigScript{ + name: "hashtype SigHashNone", + inputs: []TstInput{ + TstInput{ + txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), + sigscriptGenerates: true, + inputValidates: true, + indexOutOfRange: false, + }, + }, + hashtype: btcscript.SigHashNone, + compress: false, + scriptAtWrongIndex: false, + }, + TstSigScript{ + name: "hashtype SigHashSingle", + inputs: []TstInput{ + TstInput{ + txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), + sigscriptGenerates: true, + inputValidates: true, + indexOutOfRange: false, + }, + }, + hashtype: btcscript.SigHashSingle, + compress: false, + scriptAtWrongIndex: false, + }, + TstSigScript{ + name: "hashtype SigHashAnyoneCanPay", + inputs: []TstInput{ + TstInput{ + txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), + sigscriptGenerates: true, + inputValidates: true, + indexOutOfRange: false, + }, + }, + hashtype: btcscript.SigHashAnyOneCanPay, + compress: false, + scriptAtWrongIndex: false, + }, + TstSigScript{ + name: "hashtype non-standard", + inputs: []TstInput{ + TstInput{ + txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), + sigscriptGenerates: true, + inputValidates: true, + indexOutOfRange: false, + }, + }, + hashtype: 0x04, + compress: false, + scriptAtWrongIndex: false, + }, + TstSigScript{ + name: "invalid compression", + inputs: []TstInput{ + TstInput{ + txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), + sigscriptGenerates: true, + inputValidates: false, + indexOutOfRange: false, + }, + }, + hashtype: btcscript.SigHashAll, + compress: true, + scriptAtWrongIndex: false, + }, + TstSigScript{ + name: "short PkScript", + inputs: []TstInput{ + TstInput{ + txout: btcwire.NewTxOut(coinbaseVal, shortPkScript), + sigscriptGenerates: false, + indexOutOfRange: false, + }, + }, + hashtype: btcscript.SigHashAll, + compress: false, + scriptAtWrongIndex: false, + }, + TstSigScript{ + name: "valid script at wrong index", + inputs: []TstInput{ + TstInput{ + txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), + sigscriptGenerates: true, + inputValidates: true, + indexOutOfRange: false, + }, + TstInput{ + txout: btcwire.NewTxOut(coinbaseVal+fee, uncompressedPkScript), + sigscriptGenerates: true, + inputValidates: true, + indexOutOfRange: false, + }, + }, + hashtype: btcscript.SigHashAll, + compress: false, + scriptAtWrongIndex: true, + }, + TstSigScript{ + name: "index out of range", + inputs: []TstInput{ + TstInput{ + txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), + sigscriptGenerates: true, + inputValidates: true, + indexOutOfRange: false, + }, + TstInput{ + txout: btcwire.NewTxOut(coinbaseVal+fee, uncompressedPkScript), + sigscriptGenerates: true, + inputValidates: true, + indexOutOfRange: false, + }, + }, + hashtype: btcscript.SigHashAll, + compress: false, + scriptAtWrongIndex: true, + }, + TstSigScript{ + name: "invalid reader", + inputs: []TstInput{ + TstInput{ + txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), + invalidReader: true, + sigscriptGenerates: false, + }, + }, + hashtype: btcscript.SigHashAll, + compress: false, + scriptAtWrongIndex: true, + }, +} + +// Test the sigscript generation for valid and invalid inputs, all +// hashtypes, and with and without compression. This test creates +// sigscripts to spend fake coinbase inputs, as sigscripts cannot be +// created for the MsgTxs in txTests, since they come from the blockchain +// and we don't have the private keys. +func TestSignatureScript(t *testing.T) { + privkey := &ecdsa.PrivateKey{ + PublicKey: ecdsa.PublicKey{ + Curve: btcec.S256(), + X: new(big.Int), + Y: new(big.Int), + }, + D: new(big.Int), + } + privkey.D.SetBytes(privkeyD) + privkey.PublicKey.X.SetBytes(pubkeyX) + privkey.PublicKey.Y.SetBytes(pubkeyY) + +nexttest: + for i := range SigScriptTests { + tx := btcwire.NewMsgTx() + + output := btcwire.NewTxOut(500, []byte{btcscript.OP_RETURN}) + tx.AddTxOut(output) + + for _ = range SigScriptTests[i].inputs { + txin := btcwire.NewTxIn(coinbaseOutPoint, nil) + tx.AddTxIn(txin) + } + + var script []byte + var err error + for j := range tx.TxIn { + var idx int + if SigScriptTests[i].inputs[j].indexOutOfRange { + t.Errorf("at test %v", SigScriptTests[i].name) + idx = len(SigScriptTests[i].inputs) + } else { + idx = j + } + if SigScriptTests[i].inputs[j].invalidReader { + script, err = btcscript.TstSignatureScriptCustomReader( + new(bytes.Buffer), tx, idx, + SigScriptTests[i].inputs[j].txout.PkScript, + SigScriptTests[i].hashtype, + privkey, + SigScriptTests[i].compress) + } else { + script, err = btcscript.SignatureScript(tx, idx, + SigScriptTests[i].inputs[j].txout.PkScript, + SigScriptTests[i].hashtype, + privkey, + SigScriptTests[i].compress) + } + + if (err == nil) != SigScriptTests[i].inputs[j].sigscriptGenerates { + if err == nil { + t.Errorf("passed test '%v' incorrectly", + SigScriptTests[i].name) + } else { + t.Errorf("failed test '%v': %v", + SigScriptTests[i].name, err) + } + continue nexttest + } + if !SigScriptTests[i].inputs[j].sigscriptGenerates { + // done with this test + continue nexttest + } + + tx.TxIn[j].SignatureScript = script + } + + // If testing using a correct sigscript but for an incorrect + // index, use last input script for first input. Requires > 0 + // inputs for test. + if SigScriptTests[i].scriptAtWrongIndex { + tx.TxIn[0].SignatureScript = script + SigScriptTests[i].inputs[0].inputValidates = false + } + + // Validate tx input scripts + for j, txin := range tx.TxIn { + engine, err := btcscript.NewScript(txin.SignatureScript, + SigScriptTests[i].inputs[j].txout.PkScript, + j, tx, true) + if err != nil { + t.Errorf("cannot create script vm for test %v: %v", + SigScriptTests[i].name, err) + continue nexttest + } + err = engine.Execute() + if (err == nil) != SigScriptTests[i].inputs[j].inputValidates { + if err == nil { + t.Errorf("passed test '%v' validation incorrectly: %v", + SigScriptTests[i].name, err) + } else { + t.Errorf("failed test '%v' validation: %v", + SigScriptTests[i].name, err) + } + continue nexttest + } + } + } +} diff --git a/stack.go b/stack.go index 656c16a9..ae00f647 100644 --- a/stack.go +++ b/stack.go @@ -173,7 +173,7 @@ func (s *Stack) nipN(idx int) (so []byte, err error) { if idx == 0 { s.stk = s.stk[:sz-1] } else if idx == sz-1 { - s1 := make([][]byte, sz - 1, sz - 1) + s1 := make([][]byte, sz-1, sz-1) copy(s1, s.stk[1:]) s.stk = s1 } else { diff --git a/test_coverage.txt b/test_coverage.txt index 20a56830..8515d055 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -2,67 +2,70 @@ github.com/conformal/btcscript/address.go scriptToAddressTemplate 100.00% (58/58) github.com/conformal/btcscript/script.go Script.Step 100.00% (37/37) github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (30/30) +github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23) github.com/conformal/btcscript/script.go NewScript 100.00% (18/18) github.com/conformal/btcscript/stack.go asInt 100.00% (18/18) +github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (15/15) github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (14/14) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) -github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (14/14) github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) -github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) +github.com/conformal/btcscript/script.go sigDER 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) +github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) +github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) +github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) +github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) -github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) -github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) +github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) +github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/script.go unparseScript 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) -github.com/conformal/btcscript/script.go typeOfScript 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) +github.com/conformal/btcscript/script.go typeOfScript 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) -github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) @@ -72,76 +75,77 @@ github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) -github.com/conformal/btcscript/script.go unparseScript 100.00% (4/4) github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) -github.com/conformal/btcscript/script.go getStack 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) +github.com/conformal/btcscript/script.go getStack 100.00% (4/4) +github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) +github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) +github.com/conformal/btcscript/script.go setStack 100.00% (3/3) github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) -github.com/conformal/btcscript/script.go setStack 100.00% (3/3) -github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) -github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) github.com/conformal/btcscript/address.go ScriptToAddress 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) +github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) +github.com/conformal/btcscript/script.go PayToPubKeyHashScript 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) -github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) -github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go init 100.00% (1/1) -github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) +github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) +github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) +github.com/conformal/btcscript/opcode.go init 100.00% (1/1) +github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) +github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) +github.com/conformal/btcscript/log.go init 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) -github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) -github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) -github.com/conformal/btcscript/log.go init 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.21% (55/56) github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) +github.com/conformal/btcscript/script.go calcScriptHash 82.05% (32/39) github.com/conformal/btcscript/script.go Script.CheckErrorCondition 78.57% (11/14) github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) -github.com/conformal/btcscript/script.go Script.calcScriptHash 64.10% (25/39) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/script.go IsPushOnlyScript 0.00% (0/4) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 95.55% (901/943) +github.com/conformal/btcscript --------------------------- 96.44% (949/984) From 52a1488eaf9c1037a7e80dc29e64a2b698ce5737 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Mon, 7 Oct 2013 23:36:39 +0100 Subject: [PATCH 045/174] bitcoind only fails on invalid (undefined) opcodes when they are executed. So add entries for them that disassemble and parse ok, but will fail when executed with the appropriate error. Add a full suite of tests to confirm that this happens. Found by a strange transaction in testnet. --- internal_test.go | 13 + opcode.go | 201 ++++++++++++++ opcode_test.go | 672 +++++++++++++++++++++++++++++++++++++---------- script_test.go | 8 +- 4 files changed, 756 insertions(+), 138 deletions(-) diff --git a/internal_test.go b/internal_test.go index fb0d47d3..97d477af 100644 --- a/internal_test.go +++ b/internal_test.go @@ -129,6 +129,19 @@ func TestParseOpcode(t *testing.T) { if err == nil { t.Errorf("no error with dodgy opcode map!") } + + // Missing entry. + fakemap = make(map[byte]*opcode) + for k, v := range opcodemap { + fakemap[k] = v + } + delete(fakemap, OP_PUSHDATA4) + // this script would be fine if -8 was a valid length. + _, err = parseScriptTemplate([]byte{OP_PUSHDATA4, 0x1, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}, fakemap) + if err == nil { + t.Errorf("no error with dodgy opcode map (missing entry)!") + } } type popTest struct { diff --git a/opcode.go b/opcode.go index 83c496f3..65012698 100644 --- a/opcode.go +++ b/opcode.go @@ -223,6 +223,73 @@ const ( OP_NOP8 = 183 OP_NOP9 = 184 OP_NOP10 = 185 + OP_UNKNOWN186 = 186 + OP_UNKNOWN187 = 187 + OP_UNKNOWN188 = 188 + OP_UNKNOWN189 = 189 + OP_UNKNOWN190 = 190 + OP_UNKNOWN191 = 191 + OP_UNKNOWN192 = 192 + OP_UNKNOWN193 = 193 + OP_UNKNOWN194 = 194 + OP_UNKNOWN195 = 195 + OP_UNKNOWN196 = 196 + OP_UNKNOWN197 = 197 + OP_UNKNOWN198 = 198 + OP_UNKNOWN199 = 199 + OP_UNKNOWN200 = 200 + OP_UNKNOWN201 = 201 + OP_UNKNOWN202 = 202 + OP_UNKNOWN203 = 203 + OP_UNKNOWN204 = 204 + OP_UNKNOWN205 = 205 + OP_UNKNOWN206 = 206 + OP_UNKNOWN207 = 207 + OP_UNKNOWN208 = 208 + OP_UNKNOWN209 = 209 + OP_UNKNOWN210 = 210 + OP_UNKNOWN211 = 211 + OP_UNKNOWN212 = 212 + OP_UNKNOWN213 = 213 + OP_UNKNOWN214 = 214 + OP_UNKNOWN215 = 215 + OP_UNKNOWN216 = 216 + OP_UNKNOWN217 = 217 + OP_UNKNOWN218 = 218 + OP_UNKNOWN219 = 219 + OP_UNKNOWN220 = 220 + OP_UNKNOWN221 = 221 + OP_UNKNOWN222 = 222 + OP_UNKNOWN223 = 223 + OP_UNKNOWN224 = 224 + OP_UNKNOWN225 = 225 + OP_UNKNOWN226 = 226 + OP_UNKNOWN227 = 227 + OP_UNKNOWN228 = 228 + OP_UNKNOWN229 = 229 + OP_UNKNOWN230 = 230 + OP_UNKNOWN231 = 231 + OP_UNKNOWN232 = 232 + OP_UNKNOWN233 = 233 + OP_UNKNOWN234 = 234 + OP_UNKNOWN235 = 235 + OP_UNKNOWN236 = 236 + OP_UNKNOWN237 = 237 + OP_UNKNOWN238 = 238 + OP_UNKNOWN239 = 239 + OP_UNKNOWN240 = 240 + OP_UNKNOWN241 = 241 + OP_UNKNOWN242 = 242 + OP_UNKNOWN243 = 243 + OP_UNKNOWN244 = 244 + OP_UNKNOWN245 = 245 + OP_UNKNOWN246 = 246 + OP_UNKNOWN247 = 247 + OP_UNKNOWN248 = 248 + OP_UNKNOWN249 = 249 + OP_UNKNOWN250 = 250 + OP_UNKNOWN251 = 251 + OP_UNKNOWN252 = 252 OP_PUBKEYHASH = 253 // bitcoind internal, for completeness OP_PUBKEY = 254 // bitcoind internal, for completeness OP_INVALIDOPCODE = 255 // bitcoind internal, for completeness @@ -622,6 +689,140 @@ var opcodemapPreinit = map[byte]*opcode{ opfunc: opcodeNop}, OP_NOP10: {value: OP_NOP10, name: "OP_NOP10", length: 1, opfunc: opcodeNop}, + OP_UNKNOWN186: {value: OP_UNKNOWN186, name: "OP_UNKNOWN186", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN187: {value: OP_UNKNOWN187, name: "OP_UNKNOWN187", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN188: {value: OP_UNKNOWN188, name: "OP_UNKNOWN188", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN189: {value: OP_UNKNOWN189, name: "OP_UNKNOWN189", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN190: {value: OP_UNKNOWN190, name: "OP_UNKNOWN190", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN191: {value: OP_UNKNOWN191, name: "OP_UNKNOWN191", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN192: {value: OP_UNKNOWN192, name: "OP_UNKNOWN192", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN193: {value: OP_UNKNOWN193, name: "OP_UNKNOWN193", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN194: {value: OP_UNKNOWN194, name: "OP_UNKNOWN194", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN195: {value: OP_UNKNOWN195, name: "OP_UNKNOWN195", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN196: {value: OP_UNKNOWN196, name: "OP_UNKNOWN196", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN197: {value: OP_UNKNOWN197, name: "OP_UNKNOWN197", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN198: {value: OP_UNKNOWN198, name: "OP_UNKNOWN198", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN199: {value: OP_UNKNOWN199, name: "OP_UNKNOWN199", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN200: {value: OP_UNKNOWN200, name: "OP_UNKNOWN200", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN201: {value: OP_UNKNOWN201, name: "OP_UNKNOWN201", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN202: {value: OP_UNKNOWN202, name: "OP_UNKNOWN202", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN203: {value: OP_UNKNOWN203, name: "OP_UNKNOWN203", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN204: {value: OP_UNKNOWN204, name: "OP_UNKNOWN204", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN205: {value: OP_UNKNOWN205, name: "OP_UNKNOWN205", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN206: {value: OP_UNKNOWN206, name: "OP_UNKNOWN206", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN207: {value: OP_UNKNOWN207, name: "OP_UNKNOWN207", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN208: {value: OP_UNKNOWN208, name: "OP_UNKNOWN208", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN209: {value: OP_UNKNOWN209, name: "OP_UNKNOWN209", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN210: {value: OP_UNKNOWN210, name: "OP_UNKNOWN210", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN211: {value: OP_UNKNOWN211, name: "OP_UNKNOWN211", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN212: {value: OP_UNKNOWN212, name: "OP_UNKNOWN212", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN213: {value: OP_UNKNOWN213, name: "OP_UNKNOWN213", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN214: {value: OP_UNKNOWN214, name: "OP_UNKNOWN214", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN215: {value: OP_UNKNOWN215, name: "OP_UNKNOWN215", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN216: {value: OP_UNKNOWN216, name: "OP_UNKNOWN216", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN217: {value: OP_UNKNOWN217, name: "OP_UNKNOWN217", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN218: {value: OP_UNKNOWN218, name: "OP_UNKNOWN218", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN219: {value: OP_UNKNOWN219, name: "OP_UNKNOWN219", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN220: {value: OP_UNKNOWN220, name: "OP_UNKNOWN220", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN221: {value: OP_UNKNOWN221, name: "OP_UNKNOWN221", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN222: {value: OP_UNKNOWN222, name: "OP_UNKNOWN222", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN223: {value: OP_UNKNOWN223, name: "OP_UNKNOWN223", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN224: {value: OP_UNKNOWN224, name: "OP_UNKNOWN224", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN225: {value: OP_UNKNOWN225, name: "OP_UNKNOWN225", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN226: {value: OP_UNKNOWN226, name: "OP_UNKNOWN226", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN227: {value: OP_UNKNOWN227, name: "OP_UNKNOWN227", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN228: {value: OP_UNKNOWN228, name: "OP_UNKNOWN228", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN229: {value: OP_UNKNOWN229, name: "OP_UNKNOWN229", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN230: {value: OP_UNKNOWN230, name: "OP_UNKNOWN230", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN231: {value: OP_UNKNOWN231, name: "OP_UNKNOWN231", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN232: {value: OP_UNKNOWN232, name: "OP_UNKNOWN232", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN233: {value: OP_UNKNOWN233, name: "OP_UNKNOWN233", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN234: {value: OP_UNKNOWN234, name: "OP_UNKNOWN234", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN235: {value: OP_UNKNOWN235, name: "OP_UNKNOWN235", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN236: {value: OP_UNKNOWN236, name: "OP_UNKNOWN236", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN237: {value: OP_UNKNOWN237, name: "OP_UNKNOWN237", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN238: {value: OP_UNKNOWN238, name: "OP_UNKNOWN238", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN239: {value: OP_UNKNOWN239, name: "OP_UNKNOWN239", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN240: {value: OP_UNKNOWN240, name: "OP_UNKNOWN240", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN241: {value: OP_UNKNOWN241, name: "OP_UNKNOWN241", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN242: {value: OP_UNKNOWN242, name: "OP_UNKNOWN242", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN243: {value: OP_UNKNOWN243, name: "OP_UNKNOWN243", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN244: {value: OP_UNKNOWN244, name: "OP_UNKNOWN244", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN245: {value: OP_UNKNOWN245, name: "OP_UNKNOWN245", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN246: {value: OP_UNKNOWN246, name: "OP_UNKNOWN246", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN247: {value: OP_UNKNOWN247, name: "OP_UNKNOWN247", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN248: {value: OP_UNKNOWN248, name: "OP_UNKNOWN248", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN249: {value: OP_UNKNOWN249, name: "OP_UNKNOWN249", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN250: {value: OP_UNKNOWN250, name: "OP_UNKNOWN250", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN251: {value: OP_UNKNOWN251, name: "OP_UNKNOWN251", length: 1, + opfunc: opcodeInvalid}, + OP_UNKNOWN252: {value: OP_UNKNOWN252, name: "OP_UNKNOWN252", length: 1, + opfunc: opcodeInvalid}, OP_PUBKEYHASH: {value: OP_PUBKEYHASH, name: "OP_PUBKEYHASH", length: 1, opfunc: opcodeInvalid}, OP_PUBKEY: {value: OP_PUBKEY, name: "OP_PUBKEY", length: 1, diff --git a/opcode_test.go b/opcode_test.go index 3f647e21..151b7464 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -3416,406 +3416,810 @@ var detailedTests = []detailedTest{ // Invalid Opcodes { name: "invalid opcode 186", - script: []byte{186}, + script: []byte{btcscript.OP_UNKNOWN186}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN186", }, { name: "invalid opcode 187", - script: []byte{187}, + script: []byte{btcscript.OP_UNKNOWN187}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN187", }, { name: "invalid opcode 188", - script: []byte{188}, + script: []byte{btcscript.OP_UNKNOWN188}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN188", }, { name: "invalid opcode 189", - script: []byte{189}, + script: []byte{btcscript.OP_UNKNOWN189}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN189", }, { name: "invalid opcode 190", - script: []byte{190}, + script: []byte{btcscript.OP_UNKNOWN190}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN190", }, { name: "invalid opcode 191", - script: []byte{191}, + script: []byte{btcscript.OP_UNKNOWN191}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN191", }, { name: "invalid opcode 192", - script: []byte{192}, + script: []byte{btcscript.OP_UNKNOWN192}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN192", }, { name: "invalid opcode 193", - script: []byte{193}, + script: []byte{btcscript.OP_UNKNOWN193}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN193", }, { name: "invalid opcode 194", - script: []byte{194}, + script: []byte{btcscript.OP_UNKNOWN194}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN194", }, { name: "invalid opcode 195", - script: []byte{195}, + script: []byte{btcscript.OP_UNKNOWN195}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN195", }, { name: "invalid opcode 196", - script: []byte{196}, + script: []byte{btcscript.OP_UNKNOWN196}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN196", }, { name: "invalid opcode 197", - script: []byte{197}, + script: []byte{btcscript.OP_UNKNOWN197}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN197", }, { name: "invalid opcode 198", - script: []byte{198}, + script: []byte{btcscript.OP_UNKNOWN198}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN198", }, { name: "invalid opcode 199", - script: []byte{199}, + script: []byte{btcscript.OP_UNKNOWN199}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN199", }, { name: "invalid opcode 200", - script: []byte{200}, + script: []byte{btcscript.OP_UNKNOWN200}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN200", }, { name: "invalid opcode 201", - script: []byte{201}, + script: []byte{btcscript.OP_UNKNOWN201}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN201", }, { name: "invalid opcode 202", - script: []byte{202}, + script: []byte{btcscript.OP_UNKNOWN202}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN202", }, { name: "invalid opcode 203", - script: []byte{203}, + script: []byte{btcscript.OP_UNKNOWN203}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN203", }, { name: "invalid opcode 204", - script: []byte{204}, + script: []byte{btcscript.OP_UNKNOWN204}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN204", }, { name: "invalid opcode 205", - script: []byte{205}, + script: []byte{btcscript.OP_UNKNOWN205}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN205", }, { name: "invalid opcode 206", - script: []byte{206}, + script: []byte{btcscript.OP_UNKNOWN206}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN206", }, { name: "invalid opcode 207", - script: []byte{207}, + script: []byte{btcscript.OP_UNKNOWN207}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN207", }, { name: "invalid opcode 208", - script: []byte{208}, + script: []byte{btcscript.OP_UNKNOWN208}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN208", }, { name: "invalid opcode 209", - script: []byte{209}, + script: []byte{btcscript.OP_UNKNOWN209}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN209", }, { name: "invalid opcode 210", - script: []byte{210}, + script: []byte{btcscript.OP_UNKNOWN210}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN210", }, { name: "invalid opcode 211", - script: []byte{211}, + script: []byte{btcscript.OP_UNKNOWN211}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN211", }, { name: "invalid opcode 212", - script: []byte{212}, + script: []byte{btcscript.OP_UNKNOWN212}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN212", }, { name: "invalid opcode 213", - script: []byte{213}, + script: []byte{btcscript.OP_UNKNOWN213}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN213", }, { name: "invalid opcode 214", - script: []byte{214}, + script: []byte{btcscript.OP_UNKNOWN214}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN214", }, { name: "invalid opcode 215", - script: []byte{215}, + script: []byte{btcscript.OP_UNKNOWN215}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN215", }, { name: "invalid opcode 216", - script: []byte{216}, + script: []byte{btcscript.OP_UNKNOWN216}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN216", }, { name: "invalid opcode 217", - script: []byte{217}, + script: []byte{btcscript.OP_UNKNOWN217}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN217", }, { name: "invalid opcode 218", - script: []byte{218}, + script: []byte{btcscript.OP_UNKNOWN218}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN218", }, { name: "invalid opcode 219", - script: []byte{219}, + script: []byte{btcscript.OP_UNKNOWN219}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN219", }, { name: "invalid opcode 220", - script: []byte{220}, + script: []byte{btcscript.OP_UNKNOWN220}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN220", }, { name: "invalid opcode 221", - script: []byte{221}, + script: []byte{btcscript.OP_UNKNOWN221}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN221", }, { name: "invalid opcode 222", - script: []byte{222}, + script: []byte{btcscript.OP_UNKNOWN222}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN222", }, { name: "invalid opcode 223", - script: []byte{223}, + script: []byte{btcscript.OP_UNKNOWN223}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN223", }, { name: "invalid opcode 224", - script: []byte{224}, + script: []byte{btcscript.OP_UNKNOWN224}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN224", }, { name: "invalid opcode 225", - script: []byte{225}, + script: []byte{btcscript.OP_UNKNOWN225}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN225", }, { name: "invalid opcode 226", - script: []byte{226}, + script: []byte{btcscript.OP_UNKNOWN226}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN226", }, { name: "invalid opcode 227", - script: []byte{227}, + script: []byte{btcscript.OP_UNKNOWN227}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN227", }, { name: "invalid opcode 228", - script: []byte{228}, + script: []byte{btcscript.OP_UNKNOWN228}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN228", }, { name: "invalid opcode 229", - script: []byte{229}, + script: []byte{btcscript.OP_UNKNOWN229}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN229", }, { name: "invalid opcode 230", - script: []byte{230}, + script: []byte{btcscript.OP_UNKNOWN230}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN230", }, { name: "invalid opcode 231", - script: []byte{231}, + script: []byte{btcscript.OP_UNKNOWN231}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN231", }, { name: "invalid opcode 232", - script: []byte{232}, + script: []byte{btcscript.OP_UNKNOWN232}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN232", }, { name: "invalid opcode 233", - script: []byte{233}, + script: []byte{btcscript.OP_UNKNOWN233}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN233", }, { name: "invalid opcode 234", - script: []byte{234}, + script: []byte{btcscript.OP_UNKNOWN234}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN234", }, { name: "invalid opcode 235", - script: []byte{235}, + script: []byte{btcscript.OP_UNKNOWN235}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN235", }, { name: "invalid opcode 236", - script: []byte{236}, + script: []byte{btcscript.OP_UNKNOWN236}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN236", }, { name: "invalid opcode 237", - script: []byte{237}, + script: []byte{btcscript.OP_UNKNOWN237}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN237", }, { name: "invalid opcode 238", - script: []byte{238}, + script: []byte{btcscript.OP_UNKNOWN238}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN238", }, { name: "invalid opcode 239", - script: []byte{239}, + script: []byte{btcscript.OP_UNKNOWN239}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN239", }, { name: "invalid opcode 240", - script: []byte{240}, + script: []byte{btcscript.OP_UNKNOWN240}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN240", }, { name: "invalid opcode 241", - script: []byte{241}, + script: []byte{btcscript.OP_UNKNOWN241}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN241", }, { name: "invalid opcode 242", - script: []byte{242}, + script: []byte{btcscript.OP_UNKNOWN242}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN242", }, { name: "invalid opcode 243", - script: []byte{243}, + script: []byte{btcscript.OP_UNKNOWN243}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN243", }, { name: "invalid opcode 244", - script: []byte{244}, + script: []byte{btcscript.OP_UNKNOWN244}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN244", }, { name: "invalid opcode 245", - script: []byte{245}, + script: []byte{btcscript.OP_UNKNOWN245}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN245", }, { name: "invalid opcode 246", - script: []byte{246}, + script: []byte{btcscript.OP_UNKNOWN246}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN246", }, { name: "invalid opcode 247", - script: []byte{247}, + script: []byte{btcscript.OP_UNKNOWN247}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN247", }, { name: "invalid opcode 248", - script: []byte{248}, + script: []byte{btcscript.OP_UNKNOWN248}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN248", }, { name: "invalid opcode 249", - script: []byte{249}, + script: []byte{btcscript.OP_UNKNOWN249}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN249", }, { name: "invalid opcode 250", - script: []byte{250}, + script: []byte{btcscript.OP_UNKNOWN250}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN250", }, { name: "invalid opcode 251", - script: []byte{251}, + script: []byte{btcscript.OP_UNKNOWN251}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN251", }, { name: "invalid opcode 252", - script: []byte{252}, + script: []byte{btcscript.OP_UNKNOWN252}, expectedReturn: btcscript.StackErrInvalidOpcode, - disassemblyerr: btcscript.StackErrInvalidOpcode, + disassembly: "OP_UNKNOWN252", }, + + { + name: "invalid opcode 186 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN186, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN186 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 187 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN187, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN187 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 188 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN188, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN188 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 189 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN189, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN189 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 190 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN190, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN190 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 191 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN191, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN191 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 192 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN192, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN192 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 193 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN193, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN193 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 194 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN194, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN194 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 195 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN195, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN195 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 196 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN196, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN196 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 197 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN197, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN197 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 198 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN198, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN198 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 199 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN199, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN199 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 200 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN200, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN200 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 201 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN201, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN201 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 202 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN202, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN202 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 203 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN203, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN203 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 204 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN204, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN204 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 205 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN205, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN205 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 206 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN206, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN206 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 207 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN207, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN207 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 208 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN208, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN208 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 209 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN209, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN209 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 210 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN210, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN210 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 211 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN211, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN211 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 212 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN212, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN212 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 213 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN213, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN213 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 214 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN214, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN214 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 215 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN215, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN215 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 216 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN216, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN216 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 217 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN217, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN217 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 218 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN218, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN218 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 219 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN219, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN219 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 220 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN220, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN220 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 221 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN221, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN221 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 222 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN222, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN222 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 223 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN223, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN223 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 224 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN224, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN224 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 225 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN225, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN225 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 226 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN226, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN226 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 227 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN227, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN227 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 228 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN228, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN228 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 229 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN229, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN229 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 230 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN230, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN230 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 231 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN231, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN231 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 232 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN232, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN232 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 233 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN233, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN233 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 234 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN234, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN234 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 235 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN235, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN235 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 236 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN236, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN236 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 237 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN237, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN237 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 238 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN238, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN238 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 239 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN239, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN239 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 240 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN240, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN240 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 241 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN241, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN241 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 242 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN242, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN242 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 243 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN243, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN243 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 244 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN244, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN244 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 245 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN245, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN245 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 246 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN246, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN246 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 247 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN247, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN247 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 248 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN248, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN248 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 249 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN249, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN249 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 250 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN250, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN250 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 251 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN251, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN251 OP_ELSE OP_1 OP_ENDIF", + }, + { + name: "invalid opcode 252 if noexec", + script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN252, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + after: [][]byte{{0x01}}, + disassembly: "OP_0 OP_IF OP_UNKNOWN252 OP_ELSE OP_1 OP_ENDIF", + }, + { name: "invalid opcode OP_PUBKEY", script: []byte{btcscript.OP_PUBKEY}, diff --git a/script_test.go b/script_test.go index 951ef851..7ae51ad0 100644 --- a/script_test.go +++ b/script_test.go @@ -1355,9 +1355,9 @@ var removeOpcodeTests = []removeOpcodeTest{ }, removeOpcodeTest{ name: "invalid opcode", - before: []byte{186}, + before: []byte{btcscript.OP_UNKNOWN186}, remove: btcscript.OP_CODESEPARATOR, - err: btcscript.StackErrInvalidOpcode, + after: []byte{btcscript.OP_UNKNOWN186}, }, removeOpcodeTest{ name: "invalid length (insruction)", @@ -1463,9 +1463,9 @@ var removeOpcodeByDataTests = []removeOpcodeByDataTest{ }, removeOpcodeByDataTest{ name: "invalid opcode ", - before: []byte{187}, + before: []byte{btcscript.OP_UNKNOWN187}, remove: []byte{1, 2, 3, 4}, - err: btcscript.StackErrInvalidOpcode, + after: []byte{btcscript.OP_UNKNOWN187}, }, removeOpcodeByDataTest{ name: "invalid length (instruction)", From 83a19b239dad7921b0f23917aee9aec9c144e466 Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Tue, 8 Oct 2013 10:49:45 -0400 Subject: [PATCH 046/174] Replace ScriptToAddress with ScriptToAddrHash to return an address hash. --- address.go | 59 +++++++++++++++------------------------------ address_test.go | 63 ++++++++++++++++++++++++++++-------------------- internal_test.go | 6 ++--- 3 files changed, 60 insertions(+), 68 deletions(-) diff --git a/address.go b/address.go index 7c652abf..06708e97 100644 --- a/address.go +++ b/address.go @@ -4,11 +4,6 @@ package btcscript -import ( - "github.com/conformal/btcutil" - "github.com/conformal/btcwire" -) - // ScriptType is an enum type that represents the type of a script. It is // returned from ScriptToAddress as part of the metadata about the script. // It implements the Stringer interface for nice printing. @@ -62,8 +57,8 @@ const ( scrNoAddr ) -// ScriptToAddress extracts a payment address and the type out of a PkScript -func ScriptToAddress(script []byte) (ScriptType, string, error) { +// ScriptToAddrHash extracts a 20-byte public key hash and the type out of a PkScript +func ScriptToAddrHash(script []byte) (ScriptType, []byte, error) { // Currently this only understands one form of PkScript validformats := []pkformat{ {ScriptAddr, scrPayAddr, 25, []pkbytes{{0, OP_DUP}, {1, OP_HASH160}, {2, OP_DATA_20}, {23, OP_EQUALVERIFY}, {24, OP_CHECKSIG}}, true}, @@ -91,10 +86,10 @@ func ScriptToAddress(script []byte) (ScriptType, string, error) { {ScriptStrange, scrNoAddr, 33, []pkbytes{{0, OP_DATA_32}}, false}, {ScriptStrange, scrNoAddr, 33, []pkbytes{{0, OP_HASH160}, {1, OP_DATA_20}, {22, OP_EQUAL}}, false}, } - return scriptToAddressTemplate(script, validformats) + return scriptToAddrHashTemplate(script, validformats) } -func scriptToAddressTemplate(script []byte, validformats []pkformat) (ScriptType, string, error) { +func scriptToAddrHashTemplate(script []byte, validformats []pkformat) (ScriptType, []byte, error) { var format pkformat var success bool for _, format = range validformats { @@ -109,7 +104,7 @@ func scriptToAddressTemplate(script []byte, validformats []pkformat) (ScriptType success = true for _, pkbyte := range format.databytes { if pkbyte.off >= len(script) { - return ScriptUnknown, "Unknown", + return ScriptUnknown, nil, StackErrInvalidAddrOffset } if script[pkbyte.off] != pkbyte.val { @@ -129,64 +124,50 @@ func scriptToAddressTemplate(script []byte, validformats []pkformat) (ScriptType if len(script) > 1 { // check for a few special case if script[len(script)-1] == OP_CHECK_MULTISIG { - return ScriptStrange, "Unknown", nil + return ScriptStrange, nil, nil } if script[0] == OP_0 && (len(script) <= 75 && byte(len(script)) == script[1]+2) { - return ScriptStrange, "Unknown", nil + return ScriptStrange, nil, nil } if script[0] == OP_HASH160 && len(script) == 23 && script[22] == OP_EQUAL { - return ScriptStrange, "Unknown", nil + return ScriptStrange, nil, nil } if script[0] == OP_DATA_36 && len(script) == 37 { // Multisig ScriptSig - return ScriptStrange, "Unknown", nil + return ScriptStrange, nil, nil } } - return ScriptUnknown, "Unknown", StackErrUnknownAddress + return ScriptUnknown, nil, StackErrUnknownAddress } - var atype byte - var abuf []byte - var addr string + var addrhash []byte switch format.parsetype { case scrPayAddr: - atype = 0x00 - abuf = script[3:23] + addrhash = script[3:23] case scrCollectAddr: // script is replaced with the md160 of the pubkey slen := len(script) pubkey := script[slen-65:] - abuf = calcHash160(pubkey) + addrhash = calcHash160(pubkey) case scrCollectAddrComp: // script is replaced with the md160 of the pubkey slen := len(script) pubkey := script[slen-33:] - abuf = calcHash160(pubkey) + addrhash = calcHash160(pubkey) case scrGeneratePubkeyAddr: - atype = 0x00 - addr = "Unknown" + // unable to determine address hash from script case scrNoAddr: - addr = "Unknown" + // unable to determine address hash from script case scrPubkeyAddr: - atype = 0x00 pubkey := script[1:66] - abuf = calcHash160(pubkey) + addrhash = calcHash160(pubkey) case scrPubkeyAddrComp: - atype = 0x00 pubkey := script[1:34] - abuf = calcHash160(pubkey) + addrhash = calcHash160(pubkey) default: - return ScriptUnknown, "Unknown", StackErrInvalidParseType + return ScriptUnknown, nil, StackErrInvalidParseType } - if abuf != nil { - addrbytes := append([]byte{atype}, abuf[:]...) - - cksum := btcwire.DoubleSha256(addrbytes) - addrbytes = append(addrbytes, cksum[:4]...) - addr = btcutil.Base58Encode(addrbytes) - } - - return format.addrtype, addr, nil + return format.addrtype, addrhash, nil } diff --git a/address_test.go b/address_test.go index a969dd60..048f8a9f 100644 --- a/address_test.go +++ b/address_test.go @@ -4,13 +4,14 @@ package btcscript_test import ( + "bytes" "github.com/conformal/btcscript" "testing" ) type addressTest struct { script []byte - address string + addrhash []byte shouldFail error class btcscript.ScriptType } @@ -26,8 +27,10 @@ var addressTests = []addressTest{ 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, 0xa3, btcscript.OP_CHECKSIG}, - address: "12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S", - class: btcscript.ScriptPubKey, + addrhash: []byte{0x11, 0xb3, 0x66, 0xed, 0xfc, 0x0a, + 0x8b, 0x66, 0xfe, 0xeb, 0xae, 0x5c, 0x2e, + 0x25, 0xa7, 0xb6, 0xa5, 0xd1, 0xcf, 0x31}, + class: btcscript.ScriptPubKey, }, {script: []byte{btcscript.OP_DATA_65, 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, @@ -51,8 +54,8 @@ var addressTests = []addressTest{ 0xa4, 0xac, 0xdd, 0x12, 0x90, 0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22, 0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09, 0x01}, - address: "Unknown", - class: btcscript.ScriptPubKey, + addrhash: nil, + class: btcscript.ScriptPubKey, }, {script: []byte{btcscript.OP_DUP, btcscript.OP_HASH160, btcscript.OP_DATA_20, @@ -61,8 +64,10 @@ var addressTests = []addressTest{ 0x09, 0xa3, 0x05, 0x64, btcscript.OP_EQUALVERIFY, btcscript.OP_CHECKSIG, }, - address: "1Gmt8AzabtngttF3PcZzLR1p7uCMaHNuGY", - class: btcscript.ScriptAddr, + addrhash: []byte{0xad, 0x06, 0xdd, 0x6d, 0xde, 0xe5, + 0x5c, 0xbc, 0xa9, 0xa9, 0xe3, 0x71, 0x3b, + 0xd7, 0x58, 0x75, 0x09, 0xa3, 0x05, 0x64}, + class: btcscript.ScriptAddr, }, {script: []byte{btcscript.OP_DATA_73, 0x30, 0x46, 0x02, 0x21, 0x00, 0xdd, 0xc6, 0x97, @@ -85,8 +90,10 @@ var addressTests = []addressTest{ 0x93, 0x7d, 0x58, 0xe5, 0xa7, 0x5a, 0x71, 0x04, 0x2d, 0x40, 0x38, 0x8a, 0x4d, 0x30, 0x7f, 0x88, 0x7d}, - address: "16tRBxwU7t5hEHaPLqiE35gS3jaGBppraH", - class: btcscript.ScriptAddr, + addrhash: []byte{0x40, 0x92, 0x08, 0xf3, 0x87, 0xf4, + 0x7f, 0xd2, 0x3a, 0x9f, 0x44, 0x5e, 0x14, + 0xdc, 0x1f, 0x99, 0xbb, 0xb8, 0x0d, 0xaa}, + class: btcscript.ScriptAddr, }, {script: []byte{btcscript.OP_DATA_73, 0x30, 0x46, 0x02, 0x21, 0x00, 0xac, 0x7e, 0x4e, @@ -106,8 +113,10 @@ var addressTests = []addressTest{ 0x72, 0x3d, 0x5a, 0xd4, 0x06, 0x8d, 0xdd, 0x30, 0x36, }, - address: "1272555ceTPn2WepjzVgFESWdfNQjqdjgp", - class: btcscript.ScriptAddr, + addrhash: []byte{0x0c, 0x1b, 0x83, 0xd0, 0x1d, 0x0f, + 0xfb, 0x2b, 0xcc, 0xae, 0x60, 0x69, 0x63, + 0x37, 0x6c, 0xca, 0x38, 0x63, 0xa7, 0xce}, + class: btcscript.ScriptAddr, }, {script: []byte{btcscript.OP_DATA_32, 0x30, 0x46, 0x02, 0x21, 0x00, 0xac, 0x7e, 0x4e, @@ -115,8 +124,8 @@ var addressTests = []addressTest{ 0x87, 0x2a, 0xb9, 0xd3, 0x2c, 0xdc, 0x08, 0x33, 0x80, 0x73, 0x3e, 0x3e, 0x98, 0x47, 0xff, 0x77, }, - address: "Unknown", - class: btcscript.ScriptStrange, + addrhash: nil, + class: btcscript.ScriptStrange, }, {script: []byte{btcscript.OP_DATA_33, 0x02, 0x40, 0x05, 0xc9, 0x45, 0xd8, 0x6a, 0xc6, @@ -126,8 +135,10 @@ var addressTests = []addressTest{ 0x36, btcscript.OP_CHECKSIG, }, - address: "1272555ceTPn2WepjzVgFESWdfNQjqdjgp", - class: btcscript.ScriptPubKey, + addrhash: []byte{0x0c, 0x1b, 0x83, 0xd0, 0x1d, 0x0f, + 0xfb, 0x2b, 0xcc, 0xae, 0x60, 0x69, 0x63, + 0x37, 0x6c, 0xca, 0x38, 0x63, 0xa7, 0xce}, + class: btcscript.ScriptPubKey, }, {script: []byte{btcscript.OP_DATA_33, 0x02, 0x40, 0x05, 0xc9, 0x45, 0xd8, 0x6a, 0xc6, @@ -137,8 +148,8 @@ var addressTests = []addressTest{ 0x36, btcscript.OP_CHECK_MULTISIG, // note this isn't a real tx }, - address: "Unknown", - class: btcscript.ScriptStrange, + addrhash: nil, + class: btcscript.ScriptStrange, }, {script: []byte{btcscript.OP_0, btcscript.OP_DATA_33, 0x02, 0x40, 0x05, 0xc9, 0x45, 0xd8, 0x6a, 0xc6, @@ -147,8 +158,8 @@ var addressTests = []addressTest{ 0x72, 0x3d, 0x5a, 0xd4, 0x06, 0x8d, 0xdd, 0x30, 0x36, // note this isn't a real tx }, - address: "Unknown", - class: btcscript.ScriptStrange, + addrhash: nil, + class: btcscript.ScriptStrange, }, {script: []byte{btcscript.OP_HASH160, btcscript.OP_DATA_20, 0x02, 0x40, 0x05, 0xc9, 0x45, 0xd8, 0x6a, 0xc6, @@ -156,8 +167,8 @@ var addressTests = []addressTest{ 0xa7, 0xa8, 0x45, 0xbd, btcscript.OP_EQUAL, // note this isn't a real tx }, - address: "Unknown", - class: btcscript.ScriptStrange, + addrhash: nil, + class: btcscript.ScriptStrange, }, {script: []byte{btcscript.OP_DATA_36, 0x02, 0x40, 0x05, 0xc9, 0x45, 0xd8, 0x6a, 0xc6, @@ -167,8 +178,8 @@ var addressTests = []addressTest{ 0xa7, 0xa8, 0x45, 0xbd, // note this isn't a real tx }, - address: "Unknown", - class: btcscript.ScriptStrange, + addrhash: nil, + class: btcscript.ScriptStrange, }, {script: []byte{}, shouldFail: btcscript.StackErrUnknownAddress, @@ -177,7 +188,7 @@ var addressTests = []addressTest{ func TestAddresses(t *testing.T) { for i, s := range addressTests { - class, address, err := btcscript.ScriptToAddress(s.script) + class, addrhash, err := btcscript.ScriptToAddrHash(s.script) if s.shouldFail != nil { if err != s.shouldFail { t.Errorf("Address test %v failed is err [%v] should be [%v]", i, err, s.shouldFail) @@ -186,8 +197,8 @@ func TestAddresses(t *testing.T) { if err != nil { t.Errorf("Address test %v failed err %v", i, err) } else { - if s.address != address { - t.Errorf("Address test %v mismatch is [%v] want [%v]", i, address, s.address) + if !bytes.Equal(s.addrhash, addrhash) { + t.Errorf("Address test %v mismatch is [%v] want [%v]", i, addrhash, s.addrhash) } if s.class != class { t.Errorf("Address test %v class mismatch is [%v] want [%v]", i, class, s.class) diff --git a/internal_test.go b/internal_test.go index 97d477af..9d75ce88 100644 --- a/internal_test.go +++ b/internal_test.go @@ -49,8 +49,8 @@ func TstSignatureScriptCustomReader(reader io.Reader, tx *btcwire.MsgTx, idx int hashType, privkey, compress) } -// Tests for internal error cases in ScriptToAddress. -// We pass bad format definitions to ScriptToAddrss to make sure the internal +// Tests for internal error cases in ScriptToAddrHash. +// We pass bad format definitions to ScriptToAddrHash to make sure the internal // checks work correctly. This is located in internal_test.go and not address.go // because of the ridiculous amount of internal types/constants that would // otherwise need to be exported here. @@ -94,7 +94,7 @@ var TstPkFormats = []pkformatTest{ func TestBadPkFormat(t *testing.T) { for _, test := range TstPkFormats { - ty, addr, err := scriptToAddressTemplate(test.script, + ty, addr, err := scriptToAddrHashTemplate(test.script, []pkformat{test.format}) if err != nil { if err != test.err { From 8a743c344a643b22024a23c25dca5f0e0d458273 Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Tue, 8 Oct 2013 13:12:24 -0400 Subject: [PATCH 047/174] Update all comments and test coverage with new func name --- address.go | 4 ++-- script.go | 6 +++--- test_coverage.txt | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/address.go b/address.go index 06708e97..bc76be3f 100644 --- a/address.go +++ b/address.go @@ -5,7 +5,7 @@ package btcscript // ScriptType is an enum type that represents the type of a script. It is -// returned from ScriptToAddress as part of the metadata about the script. +// returned from ScriptToAddrHash as part of the metadata about the script. // It implements the Stringer interface for nice printing. type ScriptType int @@ -31,7 +31,7 @@ var scriptTypeToName = []string{ ScriptAddr: "Addr", ScriptPubKey: "Pubkey", ScriptStrange: "Strange", - ScriptGeneration: "Generation", // ScriptToAddress does not recieve enough information to identify Generation scripts. + ScriptGeneration: "Generation", // ScriptToAddrHash does not recieve enough information to identify Generation scripts. } type pkformat struct { diff --git a/script.go b/script.go index 86ae9198..3488d184 100644 --- a/script.go +++ b/script.go @@ -74,7 +74,7 @@ var StackErrTooManyOperations = errors.New("Too many operations in script") // the stack is over MaxScriptElementSize. var StackErrElementTooBig = errors.New("Element in script too large") -// StackErrUnknownAddress is returned when ScriptToAddress does not recognise +// StackErrUnknownAddress is returned when ScriptToAddrHash does not recognise // the pattern of the script and thus can not find the address for payment. var StackErrUnknownAddress = errors.New("non-recognised address") @@ -97,11 +97,11 @@ var StackErrEmptyStack = errors.New("Stack empty at end of execution") var StackErrP2SHNonPushOnly = errors.New("pay to script hash with non " + "pushonly input") -// StackErrInvalidParseType is an internal error returned from ScriptToAddress +// StackErrInvalidParseType is an internal error returned from ScriptToAddrHash // ony if the internal data tables are wrong. var StackErrInvalidParseType = errors.New("internal error: invalid parsetype found") -// StackErrInvalidAddrOffset is an internal error returned from ScriptToAddress +// StackErrInvalidAddrOffset is an internal error returned from ScriptToAddrHash // ony if the internal data tables are wrong. var StackErrInvalidAddrOffset = errors.New("internal error: invalid offset found") diff --git a/test_coverage.txt b/test_coverage.txt index 8515d055..fdcee9cc 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -1,5 +1,5 @@ -github.com/conformal/btcscript/address.go scriptToAddressTemplate 100.00% (58/58) +github.com/conformal/btcscript/address.go scriptToAddrHashTemplate 100.00% (45/45) github.com/conformal/btcscript/script.go Script.Step 100.00% (37/37) github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (30/30) github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23) @@ -89,7 +89,7 @@ github.com/conformal/btcscript/script.go setStack 100.00% (3/3) github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/conformal/btcscript/address.go ScriptToAddress 100.00% (2/2) +github.com/conformal/btcscript/address.go ScriptToAddrHash 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) @@ -147,5 +147,5 @@ github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/script.go IsPushOnlyScript 0.00% (0/4) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript --------------------------- 96.44% (949/984) +github.com/conformal/btcscript --------------------------- 96.40% (936/971) From 7ff3d5f8718746d23c97d37caa3946de06fd580e Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Tue, 8 Oct 2013 23:21:40 +0100 Subject: [PATCH 048/174] Handle sign extended numbers in parsing variable length opcodes. --- script.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/script.go b/script.go index 3488d184..9c98a703 100644 --- a/script.go +++ b/script.go @@ -330,7 +330,9 @@ func parseScriptTemplate(script []byte, opcodemap map[byte]*opcode) ([]parsedOpc return nil, err } off = i + 1 - op.length // beginning of data - if int(l) > len(script[off:]) { + // Disallow entries that do not fit script or were + // sign extended. + if int(l) >= len(script[off:]) || int(l) < 0 { return retScript, StackErrShortScript } pop.data = script[off : off+int(l)] From 093ddbe1935156397173ca688eb1d1c579400d0a Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Wed, 9 Oct 2013 01:27:19 +0100 Subject: [PATCH 049/174] *sigh*, accidentally commited a wrong chunk as well as the right chunk. Fix length check back to what it should be. --- script.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script.go b/script.go index 9c98a703..bd293139 100644 --- a/script.go +++ b/script.go @@ -332,7 +332,7 @@ func parseScriptTemplate(script []byte, opcodemap map[byte]*opcode) ([]parsedOpc off = i + 1 - op.length // beginning of data // Disallow entries that do not fit script or were // sign extended. - if int(l) >= len(script[off:]) || int(l) < 0 { + if int(l) > len(script[off:]) || int(l) < 0 { return retScript, StackErrShortScript } pop.data = script[off : off+int(l)] From 4e608c115fd141c12439c7706ee1120ebbc5fa4f Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Wed, 9 Oct 2013 23:59:23 +0100 Subject: [PATCH 050/174] Prevent asInt() from modifying stack data. The stack data is normally sliced from the actual script and btcscript is not supposed to ever change the tx passed into it. Add a test (and fix the other leading zeros tests) to stop this happening again. --- stack.go | 12 +++++++++--- stack_test.go | 39 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/stack.go b/stack.go index ae00f647..2a1cc556 100644 --- a/stack.go +++ b/stack.go @@ -19,10 +19,11 @@ func asInt(v []byte) *big.Int { if msb&0x80 == 0x80 { negative = true // remove sign bit - v[len(v)-1] &= 0x7f + msb &= 0x7f } + start := 0 // trim leading 0 bytes - for ; msb == 0; msb = v[len(v)-1] { + for ; msb == 0; msb, start = v[len(v)-1], start+1 { v = v[:len(v)-1] if len(v) == 0 { break @@ -31,7 +32,12 @@ func asInt(v []byte) *big.Int { // reverse bytes with a copy since stack is immutable. intArray := make([]byte, len(v)) for i := range v { - intArray[len(v)-i-1] = v[i] + // Mask off the sign bit without changing original array. + if i == 0 && start == 0 && negative { + intArray[len(v)-i -1] = v[i] & 0x7f + } else { + intArray[len(v)-i-1] = v[i] + } } num := new(big.Int).SetBytes(intArray) diff --git a/stack_test.go b/stack_test.go index f6c6e77c..19166aaf 100644 --- a/stack_test.go +++ b/stack_test.go @@ -8,6 +8,7 @@ import ( "bytes" "errors" "github.com/conformal/btcscript" + "fmt" "math/big" "testing" ) @@ -220,13 +221,14 @@ var stackTests = []stackTest{ }, { "popInt 1 leading 0", - [][]byte{{0x00000001}}, + [][]byte{{0x01, 0x00, 0x00, 0x00}}, func(stack *btcscript.Stack) error { v, err := stack.PopInt() if err != nil { return err } if v.Cmp(big.NewInt(1)) != 0 { + fmt.Printf("%v != %v\n", v, big.NewInt(1)) return errors.New("1 != 1 on popInt") } return nil @@ -234,6 +236,41 @@ var stackTests = []stackTest{ nil, [][]byte{}, }, + { + "popInt -1 leading 0", + [][]byte{{0x01,0x00, 0x00, 0x80}}, + func(stack *btcscript.Stack) error { + v, err := stack.PopInt() + if err != nil { + return err + } + if v.Cmp(big.NewInt(-1)) != 0 { + fmt.Printf("%v != %v\n", v, big.NewInt(-1)) + return errors.New("-1 != -1 on popInt") + } + return nil + }, + nil, + [][]byte{}, + }, + // Confirm that the asInt code doesn't modify the base data. + { + "peekint nomodify -1", + [][]byte{{0x01,0x00, 0x00, 0x80}}, + func(stack *btcscript.Stack) error { + v, err := stack.PeekInt(0) + if err != nil { + return err + } + if v.Cmp(big.NewInt(-1)) != 0 { + fmt.Printf("%v != %v\n", v, big.NewInt(-1)) + return errors.New("-1 != -1 on popInt") + } + return nil + }, + nil, + [][]byte{{0x01,0x00, 0x00, 0x80}}, + }, { "PushInt 0", [][]byte{}, From 53ca29efadb8b3f4467a0f1e6782b7004e6b23c6 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Thu, 10 Oct 2013 00:20:14 +0100 Subject: [PATCH 051/174] fix multi-byte bug in previous. Use the right offset when working out if we should mask off the sign bit. Add more tests that would have caught this case. --- stack.go | 2 +- stack_test.go | 34 ++++++++++++++++++++++++++++++++++ test_coverage.txt | 4 ++-- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/stack.go b/stack.go index 2a1cc556..0f72e2a0 100644 --- a/stack.go +++ b/stack.go @@ -33,7 +33,7 @@ func asInt(v []byte) *big.Int { intArray := make([]byte, len(v)) for i := range v { // Mask off the sign bit without changing original array. - if i == 0 && start == 0 && negative { + if i == len(v) -1 && start == 0 && negative { intArray[len(v)-i -1] = v[i] & 0x7f } else { intArray[len(v)-i-1] = v[i] diff --git a/stack_test.go b/stack_test.go index 19166aaf..e0b09995 100644 --- a/stack_test.go +++ b/stack_test.go @@ -236,6 +236,22 @@ var stackTests = []stackTest{ nil, [][]byte{}, }, + { + "popInt -1", + [][]byte{{0x81}}, + func(stack *btcscript.Stack) error { + v, err := stack.PopInt() + if err != nil { + return err + } + if v.Cmp(big.NewInt(-1)) != 0 { + return errors.New("1 != 1 on popInt") + } + return nil + }, + nil, + [][]byte{}, + }, { "popInt -1 leading 0", [][]byte{{0x01,0x00, 0x00, 0x80}}, @@ -253,6 +269,24 @@ var stackTests = []stackTest{ nil, [][]byte{}, }, + // Triggers the multibyte case in asInt + { + "popInt -513", + [][]byte{{0x1, 0x82}}, + func(stack *btcscript.Stack) error { + v, err := stack.PopInt() + if err != nil { + return err + } + if v.Cmp(big.NewInt(-513)) != 0 { + fmt.Printf("%v != %v\n", v, big.NewInt(-513)) + return errors.New("1 != 1 on popInt") + } + return nil + }, + nil, + [][]byte{}, + }, // Confirm that the asInt code doesn't modify the base data. { "peekint nomodify -1", diff --git a/test_coverage.txt b/test_coverage.txt index fdcee9cc..cddc5fc8 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -3,8 +3,8 @@ github.com/conformal/btcscript/address.go scriptToAddrHashTemplate 100.00% (45 github.com/conformal/btcscript/script.go Script.Step 100.00% (37/37) github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (30/30) github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23) +github.com/conformal/btcscript/stack.go asInt 100.00% (21/21) github.com/conformal/btcscript/script.go NewScript 100.00% (18/18) -github.com/conformal/btcscript/stack.go asInt 100.00% (18/18) github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (15/15) github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (14/14) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) @@ -147,5 +147,5 @@ github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/script.go IsPushOnlyScript 0.00% (0/4) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript --------------------------- 96.40% (936/971) +github.com/conformal/btcscript --------------------------- 96.41% (939/974) From 003a41f66f5840674faa94022bc3cbd8892bb32e Mon Sep 17 00:00:00 2001 From: Dale Rahn Date: Wed, 9 Oct 2013 19:24:40 -0400 Subject: [PATCH 052/174] Slightly cleaner fix. --- stack.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/stack.go b/stack.go index 0f72e2a0..b09b2322 100644 --- a/stack.go +++ b/stack.go @@ -15,15 +15,15 @@ func asInt(v []byte) *big.Int { return big.NewInt(0) } negative := false + origlen := len(v) msb := v[len(v)-1] if msb&0x80 == 0x80 { negative = true // remove sign bit msb &= 0x7f } - start := 0 // trim leading 0 bytes - for ; msb == 0; msb, start = v[len(v)-1], start+1 { + for ; msb == 0; msb = v[len(v)-1] { v = v[:len(v)-1] if len(v) == 0 { break @@ -32,12 +32,12 @@ func asInt(v []byte) *big.Int { // reverse bytes with a copy since stack is immutable. intArray := make([]byte, len(v)) for i := range v { - // Mask off the sign bit without changing original array. - if i == len(v) -1 && start == 0 && negative { - intArray[len(v)-i -1] = v[i] & 0x7f - } else { - intArray[len(v)-i-1] = v[i] - } + intArray[len(v)-i-1] = v[i] + } + // IFF the value is negative and no 0 bytes were trimmed, + // the leading byte needs to be sign corrected + if negative && len(intArray) == origlen { + intArray[0] &= 0x7f } num := new(big.Int).SetBytes(intArray) From 40c75b27ac8103234379ef8243a8393019c8c708 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Wed, 9 Oct 2013 00:13:52 +0100 Subject: [PATCH 053/174] Add CalcScriptInfo entrypoint to return info about scriptpairs. Specficially the class of the pkScript, the expected numbers of arguments and the number of sigops. --- script.go | 101 ++++++++++++++++ script_test.go | 295 ++++++++++++++++++++++++++++++++++++++++++---- stack_test.go | 8 +- test_coverage.txt | 128 ++++++++++---------- 4 files changed, 442 insertions(+), 90 deletions(-) diff --git a/script.go b/script.go index bd293139..10871793 100644 --- a/script.go +++ b/script.go @@ -109,6 +109,10 @@ var StackErrInvalidAddrOffset = errors.New("internal error: invalid offset found // a function. var StackErrInvalidIndex = errors.New("Invalid script index") +// StackErrNonPushOnly is returned when ScriptInfo is called with a pkScript +// that peforms operations other that pushing data to the stack. +var StackErrNonPushOnly = errors.New("SigScript is non pushonly") + // Bip16Activation is the timestamp where BIP0016 is valid to use in the // blockchain. To be used to determine if BIP0016 should be called for or not. // This timestamp corresponds to Sun Apr 1 00:00:00 UTC 2012. @@ -975,3 +979,100 @@ func sigDER(r, s *big.Int) []byte { copy(b[offset+2:], s.Bytes()) return b } + +// expectedInputs returns the number of arguments required by a script. +// If the script is of unnown type such that the number can not be determined +// then -1 is returned. We are an interanl function and thus assume that class +// is the real class of pops (and we can thus assume things that were +// determined while finding out the type). +func expectedInputs(pops []parsedOpcode, class ScriptClass) int { + // count needed inputs. + switch class { + case PubKeyTy: + return 1 + case PubKeyHashTy: + return 2 + case ScriptHashTy: + // Not including script, handled below. + return 1 + case MultiSigTy: + // Standard multisig has a push a small number for the number + // of sigs and number of keys. + // Check the first push instrution to see how many arguments are + // expected. typoeOfScript already checked this so that we know + // it'll be one of OP_1 - OP_16. + return int(pops[0].opcode.value - (OP_1 - 1)) + default: + return -1 + } + +} + +type ScriptInfo struct { + // The class of the sigscript, equivalent to calling GetScriptClass + // on the sigScript. + PkScriptClass ScriptClass + // the number of inputs provided by the pkScript + NumInputs int + // the number of outputs required by sigScript and any + // pay-to-script-hash scripts. The number will be -1 if unknown. + ExpectedInputs int + // The nubmer of signature operations in the scriptpair. + SigOps int +} + +// CalcScriptInfo returns a structure providing data about the scriptpair that +// are provided as arguments. It will error if the pair is in someway invalid +// such taht they can not be analysed, i.e. if they do not parse or the +// pkScript is not a push-only script +func CalcScriptInfo(sigscript, pkscript []byte, bip16 bool) (*ScriptInfo, error) { + si := new(ScriptInfo) + // parse both scripts. + sigPops, err := parseScript(sigscript) + if err != nil { + return nil, err + } + + pkPops, err := parseScript(pkscript) + if err != nil { + return nil, err + } + + // push only sigScript makes little sense. + si.PkScriptClass = typeOfScript(pkPops) + + // Can't have a pkScript that doesn't just push data. + if !isPushOnly(sigPops) { + return nil, StackErrNonPushOnly + } + + si.ExpectedInputs = expectedInputs(pkPops, si.PkScriptClass) + // all entries push to stack (or are OP_RESERVED and exec will fail). + si.NumInputs = len(sigPops) + + if si.PkScriptClass == ScriptHashTy && bip16 { + // grab the last push instruction in the script and pull out the + // data. + script := sigPops[len(sigPops)-1].data + // check for existance and error else. + shPops, err := parseScript(script) + if err != nil { + return nil, err + } + + shClass := typeOfScript(shPops) + + shInputs := expectedInputs(shPops, shClass) + if shInputs == -1 { + // We have no fucking clue, then. + si.ExpectedInputs = -1 + } else { + si.ExpectedInputs += shInputs + } + si.SigOps = getSigOpCount(shPops, true) + } else { + si.SigOps = getSigOpCount(pkPops, true) + } + + return si, nil +} diff --git a/script_test.go b/script_test.go index 7ae51ad0..0caee16b 100644 --- a/script_test.go +++ b/script_test.go @@ -15,15 +15,17 @@ import ( ) type txTest struct { - name string - tx *btcwire.MsgTx - pkScript []byte // output script of previous tx - idx int // tx idx to be run. - bip16 bool // is bip16 active? - parseErr error // failure of NewScript - err error // Failure of Executre - shouldFail bool // Execute should fail with nonspecified error. - nSigOps int // result of GetPreciseSigOpsCount + name string + tx *btcwire.MsgTx + pkScript []byte // output script of previous tx + idx int // tx idx to be run. + bip16 bool // is bip16 active? + parseErr error // failure of NewScript + err error // Failure of Executre + shouldFail bool // Execute should fail with nonspecified error. + nSigOps int // result of GetPreciseSigOpsCount + scriptInfo btcscript.ScriptInfo // result of ScriptInfo + scriptInfoErr error // error return of ScriptInfo } var txTests = []txTest{ @@ -127,6 +129,12 @@ var txTests = []txTest{ }, idx: 0, nSigOps: 1, + scriptInfo: btcscript.ScriptInfo{ + PkScriptClass: btcscript.PubKeyTy, + NumInputs: 1, + ExpectedInputs: 1, + SigOps: 1, + }, }, // Previous test with the value of one output changed. txTest{ @@ -228,6 +236,12 @@ var txTests = []txTest{ idx: 0, err: btcscript.StackErrScriptFailed, nSigOps: 1, + scriptInfo: btcscript.ScriptInfo{ + PkScriptClass: btcscript.PubKeyTy, + NumInputs: 1, + ExpectedInputs: 1, + SigOps: 1, + }, }, txTest{ name: "CheckSig invalid signature", @@ -330,6 +344,12 @@ var txTests = []txTest{ idx: 0, shouldFail: true, nSigOps: 1, + scriptInfo: btcscript.ScriptInfo{ + PkScriptClass: btcscript.PubKeyTy, + NumInputs: 1, + ExpectedInputs: 1, + SigOps: 1, + }, }, txTest{ name: "CheckSig invalid pubkey", @@ -431,6 +451,12 @@ var txTests = []txTest{ idx: 0, shouldFail: true, nSigOps: 1, + scriptInfo: btcscript.ScriptInfo{ + PkScriptClass: btcscript.PubKeyTy, + NumInputs: 1, + ExpectedInputs: 1, + SigOps: 1, + }, }, // tx 599e47a8114fe098103663029548811d2651991b62397e057f0c863c2bc9f9ea // uses checksig with SigHashNone. @@ -533,6 +559,12 @@ var txTests = []txTest{ idx: 0, bip16: true, // after threshold nSigOps: 1, + scriptInfo: btcscript.ScriptInfo{ + PkScriptClass: btcscript.PubKeyHashTy, + NumInputs: 2, + ExpectedInputs: 2, + SigOps: 1, + }, }, // tx 51bf528ecf3c161e7c021224197dbe84f9a8564212f6207baa014c01a1668e1e // first instance of an AnyoneCanPay signature in the blockchain @@ -657,6 +689,12 @@ var txTests = []txTest{ idx: 0, bip16: true, // after threshold nSigOps: 1, + scriptInfo: btcscript.ScriptInfo{ + PkScriptClass: btcscript.PubKeyHashTy, + NumInputs: 2, + ExpectedInputs: 2, + SigOps: 1, + }, }, // tx 6d36bc17e947ce00bb6f12f8e7a56a1585c5a36188ffa2b05e10b4743273a74b // Uses OP_CODESEPARATOR and OP_CHECKMULTISIG @@ -777,9 +815,10 @@ var txTests = []txTest{ 0x4f, 0x13, btcscript.OP_NOP2, btcscript.OP_DROP, }, - idx: 1, - bip16: false, - nSigOps: 0, // multisig is in the pkScript! + idx: 1, + bip16: false, + nSigOps: 0, // multisig is in the pkScript! + scriptInfoErr: btcscript.StackErrNonPushOnly, }, // same as previous but with one byte changed to make signature fail txTest{ @@ -899,10 +938,11 @@ var txTests = []txTest{ 0x4f, 0x13, btcscript.OP_NOP2, btcscript.OP_DROP, }, - idx: 1, - bip16: false, - err: btcscript.StackErrScriptFailed, - nSigOps: 0, // multisig is in the pkScript! + idx: 1, + bip16: false, + err: btcscript.StackErrScriptFailed, + nSigOps: 0, // multisig is in the pkScript! + scriptInfoErr: btcscript.StackErrNonPushOnly, }, // tx e5779b9e78f9650debc2893fd9636d827b26b4ddfa6a8172fe8708c924f5c39d // First P2SH transaction in the blockchain @@ -962,6 +1002,12 @@ var txTests = []txTest{ idx: 0, bip16: true, nSigOps: 0, // no signature ops in the pushed script. + scriptInfo: btcscript.ScriptInfo{ + PkScriptClass: btcscript.ScriptHashTy, + NumInputs: 1, + ExpectedInputs: -1, // p2sh script is non standard + SigOps: 0, + }, }, // next few tests are modified versions of previous to hit p2sh error // cases. @@ -1023,6 +1069,12 @@ var txTests = []txTest{ err: btcscript.StackErrScriptFailed, bip16: true, nSigOps: 0, // no signature ops in the pushed script. + scriptInfo: btcscript.ScriptInfo{ + PkScriptClass: btcscript.ScriptHashTy, + NumInputs: 1, + ExpectedInputs: -1, // p2sh script is non standard + SigOps: 0, + }, }, txTest{ // sigscript changed so that pkscript hash will not match. @@ -1078,9 +1130,10 @@ var txTests = []txTest{ 0xba, 0x67, btcscript.OP_EQUAL, }, - idx: 0, - err: btcscript.StackErrShortScript, - bip16: true, + idx: 0, + err: btcscript.StackErrShortScript, + bip16: true, + scriptInfoErr: btcscript.StackErrShortScript, }, txTest{ // sigscript changed so to be non pushonly. @@ -1140,10 +1193,11 @@ var txTests = []txTest{ 0xae, 0x88, btcscript.OP_EQUAL, }, - idx: 0, - parseErr: btcscript.StackErrP2SHNonPushOnly, - bip16: true, - nSigOps: 0, // no signature ops in the pushed script. + idx: 0, + parseErr: btcscript.StackErrP2SHNonPushOnly, + bip16: true, + nSigOps: 0, // no signature ops in the pushed script. + scriptInfoErr: btcscript.StackErrNonPushOnly, }, txTest{ // sigscript changed so to be non pushonly. @@ -1195,6 +1249,12 @@ var txTests = []txTest{ idx: 0, bip16: true, nSigOps: 0, // no signature ops in the pushed script. + scriptInfo: btcscript.ScriptInfo{ + PkScriptClass: btcscript.NonStandardTy, + NumInputs: 1, + ExpectedInputs: -1, + SigOps: 0, + }, }, } @@ -1319,6 +1379,195 @@ func TestGetPreciseSignOps(t *testing.T) { } } +type scriptInfoTest struct { + name string + sigScript []byte + pkScript []byte + bip16 bool + scriptInfo btcscript.ScriptInfo + scriptInfoErr error +} + +func TestScriptInfo(t *testing.T) { + for _, test := range txTests { + si, err := btcscript.CalcScriptInfo( + test.tx.TxIn[test.idx].SignatureScript, + test.pkScript, test.bip16) + if err != nil { + if err != test.scriptInfoErr { + t.Errorf("scriptinfo test \"%s\": got \"%v\""+ + "expected \"%v\"", test.name, err, + test.scriptInfoErr) + } + continue + } + if test.scriptInfoErr != nil { + t.Errorf("%s: succeeded when expecting \"%v\"", + test.name, test.scriptInfoErr) + continue + } + if *si != test.scriptInfo { + t.Errorf("%s: scriptinfo doesn't match expected. "+ + "got: \"%v\" expected \"%v\"", test.name, + *si, test.scriptInfo) + continue + } + } + + extraTests := []scriptInfoTest{ + { + // Invented scripts, the hashes do not match + name: "pkscript doesn't parse", + sigScript: []byte{btcscript.OP_TRUE, + btcscript.OP_DATA_1, 81, + btcscript.OP_DATA_8, + btcscript.OP_2DUP, btcscript.OP_EQUAL, + btcscript.OP_NOT, btcscript.OP_VERIFY, + btcscript.OP_ABS, btcscript.OP_SWAP, + btcscript.OP_ABS, btcscript.OP_EQUAL, + }, + // truncated version of test below: + pkScript: []byte{btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0xfe, 0x44, 0x10, 0x65, 0xb6, 0x53, 0x22, 0x31, + 0xde, 0x2f, 0xac, 0x56, 0x31, 0x52, 0x20, 0x5e, + 0xc4, 0xf5, 0x9c, + }, + bip16: true, + scriptInfoErr: btcscript.StackErrShortScript, + }, + { + name: "sigScript doesn't parse", + // Truncated version of p2sh script below. + sigScript: []byte{btcscript.OP_TRUE, + btcscript.OP_DATA_1, 81, + btcscript.OP_DATA_8, + btcscript.OP_2DUP, btcscript.OP_EQUAL, + btcscript.OP_NOT, btcscript.OP_VERIFY, + btcscript.OP_ABS, btcscript.OP_SWAP, + btcscript.OP_ABS, + }, + pkScript: []byte{btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0xfe, 0x44, 0x10, 0x65, 0xb6, 0x53, 0x22, 0x31, + 0xde, 0x2f, 0xac, 0x56, 0x31, 0x52, 0x20, 0x5e, + 0xc4, 0xf5, 0x9c, 0x74, btcscript.OP_EQUAL, + }, + bip16: true, + scriptInfoErr: btcscript.StackErrShortScript, + }, + { + // Invented scripts, the hashes do not match + name: "p2sh standard script", + sigScript: []byte{btcscript.OP_TRUE, + btcscript.OP_DATA_1, 81, + btcscript.OP_DATA_25, + btcscript.OP_DUP, btcscript.OP_HASH160, + btcscript.OP_DATA_20, 0x1, 0x2, 0x3, 0x4, 0x5, + 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, + 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, + btcscript.OP_EQUALVERIFY, btcscript.OP_CHECKSIG, + }, + pkScript: []byte{btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0xfe, 0x44, 0x10, 0x65, 0xb6, 0x53, 0x22, 0x31, + 0xde, 0x2f, 0xac, 0x56, 0x31, 0x52, 0x20, 0x5e, + 0xc4, 0xf5, 0x9c, 0x74, btcscript.OP_EQUAL, + }, + bip16: true, + scriptInfo: btcscript.ScriptInfo{ + PkScriptClass: btcscript.ScriptHashTy, + NumInputs: 3, + ExpectedInputs: 3, // nonstandard p2sh. + SigOps: 1, + }, + }, + { + // from 567a53d1ce19ce3d07711885168484439965501536d0d0294c5d46d46c10e53b + // from the blockchain. + name: "p2sh nonstandard script", + sigScript: []byte{btcscript.OP_TRUE, + btcscript.OP_DATA_1, 81, + btcscript.OP_DATA_8, + btcscript.OP_2DUP, btcscript.OP_EQUAL, + btcscript.OP_NOT, btcscript.OP_VERIFY, + btcscript.OP_ABS, btcscript.OP_SWAP, + btcscript.OP_ABS, btcscript.OP_EQUAL, + }, + pkScript: []byte{btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0xfe, 0x44, 0x10, 0x65, 0xb6, 0x53, 0x22, 0x31, + 0xde, 0x2f, 0xac, 0x56, 0x31, 0x52, 0x20, 0x5e, + 0xc4, 0xf5, 0x9c, 0x74, btcscript.OP_EQUAL, + }, + bip16: true, + scriptInfo: btcscript.ScriptInfo{ + PkScriptClass: btcscript.ScriptHashTy, + NumInputs: 3, + ExpectedInputs: -1, // nonstandard p2sh. + SigOps: 0, + }, + }, + { + // Script is invented, numbers all fake. + name: "multisig script", + sigScript: []byte{btcscript.OP_TRUE, + btcscript.OP_TRUE, btcscript.OP_TRUE, + }, + pkScript: []byte{ + btcscript.OP_3, btcscript.OP_DATA_33, + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, + 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, + 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, + 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, + btcscript.OP_DATA_33, + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, + 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, + 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, + 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, + btcscript.OP_DATA_33, + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, + 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, + 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, + 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, + btcscript.OP_3, btcscript.OP_CHECK_MULTISIG, + }, + bip16: true, + scriptInfo: btcscript.ScriptInfo{ + PkScriptClass: btcscript.MultiSigTy, + NumInputs: 3, + ExpectedInputs: 3, + SigOps: 3, + }, + }, + } + + for _, test := range extraTests { + si, err := btcscript.CalcScriptInfo(test.sigScript, + test.pkScript, test.bip16) + if err != nil { + if err != test.scriptInfoErr { + t.Errorf("scriptinfo test \"%s\": got \"%v\""+ + "expected \"%v\"", test.name, err, + test.scriptInfoErr) + } + continue + } + if test.scriptInfoErr != nil { + t.Errorf("%s: succeeded when expecting \"%v\"", + test.name, test.scriptInfoErr) + continue + } + if *si != test.scriptInfo { + t.Errorf("%s: scriptinfo doesn't match expected. "+ + "got: \"%v\" expected \"%v\"", test.name, + *si, test.scriptInfo) + continue + } + } + +} + type removeOpcodeTest struct { name string before []byte diff --git a/stack_test.go b/stack_test.go index e0b09995..0bf76c03 100644 --- a/stack_test.go +++ b/stack_test.go @@ -7,8 +7,8 @@ package btcscript_test import ( "bytes" "errors" - "github.com/conformal/btcscript" "fmt" + "github.com/conformal/btcscript" "math/big" "testing" ) @@ -254,7 +254,7 @@ var stackTests = []stackTest{ }, { "popInt -1 leading 0", - [][]byte{{0x01,0x00, 0x00, 0x80}}, + [][]byte{{0x01, 0x00, 0x00, 0x80}}, func(stack *btcscript.Stack) error { v, err := stack.PopInt() if err != nil { @@ -290,7 +290,7 @@ var stackTests = []stackTest{ // Confirm that the asInt code doesn't modify the base data. { "peekint nomodify -1", - [][]byte{{0x01,0x00, 0x00, 0x80}}, + [][]byte{{0x01, 0x00, 0x00, 0x80}}, func(stack *btcscript.Stack) error { v, err := stack.PeekInt(0) if err != nil { @@ -303,7 +303,7 @@ var stackTests = []stackTest{ return nil }, nil, - [][]byte{{0x01,0x00, 0x00, 0x80}}, + [][]byte{{0x01, 0x00, 0x00, 0x80}}, }, { "PushInt 0", diff --git a/test_coverage.txt b/test_coverage.txt index cddc5fc8..0e9376e9 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -2,70 +2,72 @@ github.com/conformal/btcscript/address.go scriptToAddrHashTemplate 100.00% (45/45) github.com/conformal/btcscript/script.go Script.Step 100.00% (37/37) github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (30/30) +github.com/conformal/btcscript/script.go CalcScriptInfo 100.00% (25/25) github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23) github.com/conformal/btcscript/stack.go asInt 100.00% (21/21) github.com/conformal/btcscript/script.go NewScript 100.00% (18/18) github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (15/15) -github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (14/14) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) +github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (14/14) +github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) -github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) -github.com/conformal/btcscript/script.go sigDER 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) +github.com/conformal/btcscript/script.go sigDER 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) -github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) +github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) -github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) -github.com/conformal/btcscript/script.go unparseScript 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) +github.com/conformal/btcscript/script.go unparseScript 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) github.com/conformal/btcscript/script.go typeOfScript 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) +github.com/conformal/btcscript/script.go expectedInputs 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) @@ -75,69 +77,69 @@ github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) -github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) -github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) +github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) github.com/conformal/btcscript/script.go setStack 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) -github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/conformal/btcscript/address.go ScriptToAddrHash 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) -github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/conformal/btcscript/script.go PayToPubKeyHashScript 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) +github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) +github.com/conformal/btcscript/script.go PayToPubKeyHashScript 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) -github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/conformal/btcscript/address.go ScriptToAddrHash 100.00% (2/2) github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) +github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) github.com/conformal/btcscript/opcode.go init 100.00% (1/1) -github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) +github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) github.com/conformal/btcscript/log.go init 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.21% (55/56) github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) github.com/conformal/btcscript/script.go calcScriptHash 82.05% (32/39) @@ -147,5 +149,5 @@ github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/script.go IsPushOnlyScript 0.00% (0/4) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript --------------------------- 96.41% (939/974) +github.com/conformal/btcscript --------------------------- 96.52% (970/1005) From 8eead5217d6af35b9def1558fc0529bac3af5067 Mon Sep 17 00:00:00 2001 From: David Hill Date: Thu, 24 Oct 2013 10:13:58 -0400 Subject: [PATCH 054/174] Add flag bitmask to NewScript for canonical sig checks. This removes the bip16 bool from NewScript and adds it to flags (with the constant ScriptBip16), and also adds a new flag, ScriptCanonicalSignatures, which will call btcec.ParseDERSignature parsing a signature during an Execute. This is needed to emulate bitcoind behavior, as bitcoind performs canonical signature validation (DER format) in some places (like mempool acceptance) but not others (like block validation). Updated tests and test coverage file to reflect changes. --- opcode.go | 22 ++++-- opcode_test.go | 26 ++++++- script.go | 62 +++++++++++++-- script_test.go | 189 +++++++++++++++++++++++++++++++++++++++++++++- test_coverage.txt | 12 +-- 5 files changed, 286 insertions(+), 25 deletions(-) diff --git a/opcode.go b/opcode.go index 65012698..21a4ee18 100644 --- a/opcode.go +++ b/opcode.go @@ -1682,7 +1682,12 @@ func opcodeCheckSig(op *parsedOpcode, s *Script) error { return err } - signature, err := btcec.ParseSignature(sigStr, btcec.S256()) + var signature *btcec.Signature + if s.der { + signature, err = btcec.ParseDERSignature(sigStr, btcec.S256()) + } else { + signature, err = btcec.ParseSignature(sigStr, btcec.S256()) + } if err != nil { log.Warnf("can't parse signature from string: %v", err) return err @@ -1761,10 +1766,17 @@ func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error { return err } // skip off the last byte for hashtype - signatures[i], err = - btcec.ParseSignature( - sigStrings[i][:len(sigStrings[i])-1], - btcec.S256()) + if s.der { + signatures[i], err = + btcec.ParseDERSignature( + sigStrings[i][:len(sigStrings[i])-1], + btcec.S256()) + } else { + signatures[i], err = + btcec.ParseSignature( + sigStrings[i][:len(sigStrings[i])-1], + btcec.S256()) + } if err != nil { return err } diff --git a/opcode_test.go b/opcode_test.go index 151b7464..d757463e 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -19,6 +19,7 @@ import ( // All run on a fake tx with a single in, single out. type opcodeTest struct { script []byte + canonical bool shouldPass bool shouldFail error } @@ -384,6 +385,18 @@ var opcodeTests = []opcodeTest{ 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, btcscript.OP_1, btcscript.OP_CHECK_MULTISIG}, + canonical: false, + shouldPass: false}, + {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_DATA_65, + 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, + 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, + 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, 0x71, 0x30, 0x2f, + 0xa2, 0x84, 0x14, 0xe7, 0xaa, 0xb3, 0x73, 0x97, 0xf5, 0x54, + 0xa7, 0xdf, 0x5f, 0x14, 0x2c, 0x21, 0xc1, 0xb7, 0x30, 0x3b, + 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, + 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, + btcscript.OP_1, btcscript.OP_CHECK_MULTISIG}, + canonical: true, shouldPass: false}, /* up here because no defined error case. */ {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_DATA_65, @@ -468,7 +481,7 @@ var opcodeTests = []opcodeTest{ {script: []byte{252}, shouldPass: false}, } -func testScript(t *testing.T, script []byte) (err error) { +func testScript(t *testing.T, script []byte, canonical bool) (err error) { // mock up fake tx. tx := &btcwire.MsgTx{ Version: 1, @@ -493,8 +506,13 @@ func testScript(t *testing.T, script []byte) (err error) { tx.TxOut[0].PkScript = script + var flags btcscript.ScriptFlags + if canonical { + flags = btcscript.ScriptCanonicalSignatures + } + engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript, - tx.TxOut[0].PkScript, 0, tx, false) + tx.TxOut[0].PkScript, 0, tx, flags) if err != nil { return err } @@ -514,7 +532,7 @@ func TestScripts(t *testing.T) { for i := range opcodeTests { shouldPass := opcodeTests[i].shouldPass shouldFail := opcodeTests[i].shouldFail - err := testScript(t, opcodeTests[i].script) + err := testScript(t, opcodeTests[i].script, opcodeTests[i].canonical) if shouldFail != nil { if err == nil { t.Errorf("test %d passed should fail with %v", i, err) @@ -4279,7 +4297,7 @@ func testOpcode(t *testing.T, test *detailedTest) { tx.TxOut[0].PkScript = test.script engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript, - tx.TxOut[0].PkScript, 0, tx, false) + tx.TxOut[0].PkScript, 0, tx, 0) if err != nil { if err != test.expectedReturn { t.Errorf("Error return not expected %s: %v %v", diff --git a/script.go b/script.go index 10871793..9aa814bb 100644 --- a/script.go +++ b/script.go @@ -159,6 +159,7 @@ type Script struct { condStack []int numOps int bip16 bool // treat execution as pay-to-script-hash + der bool // enforce DER encoding savedFirstStack [][]byte // stack from first script for bip16 scripts } @@ -361,11 +362,35 @@ func unparseScript(pops []parsedOpcode) ([]byte, error) { return script, nil } +// ScriptFlags is a bitmask defining additional operations or +// tests that will be done when executing a Script. +type ScriptFlags uint32 + +const ( + // ScriptBip16 defines whether the bip16 threshhold has passed and thus + // pay-to-script hash transactions will be fully validated. + ScriptBip16 ScriptFlags = 1 << iota + + // ScriptCanonicalSignatures defines whether additional canonical + // signature checks are performed when parsing a signature. + // + // Canonical (DER) signatures are not required in the tx rules for + // block acceptance, but are checked in recent versions of bitcoind + // when accepting transactions to the mempool. Non-canonical (valid + // BER but not valid DER) transactions can potentially be changed + // before mined into a block, either by adding extra padding or + // flipping the sign of the R or S value in the signature, creating a + // transaction that still validates and spends the inputs, but is not + // recognized by creator of the transaction. Performing a canonical + // check enforces script signatures use a unique DER format. + ScriptCanonicalSignatures +) + // NewScript returns a new script engine for the provided tx and input idx with // a signature script scriptSig and a pubkeyscript scriptPubKey. If bip16 is // true then it will be treated as if the bip16 threshhold has passed and thus // pay-to-script hash transactions will be fully validated. -func NewScript(scriptSig []byte, scriptPubKey []byte, txidx int, tx *btcwire.MsgTx, bip16 bool) (*Script, error) { +func NewScript(scriptSig []byte, scriptPubKey []byte, txidx int, tx *btcwire.MsgTx, flags ScriptFlags) (*Script, error) { var m Script scripts := [][]byte{scriptSig, scriptPubKey} m.scripts = make([][]parsedOpcode, len(scripts)) @@ -385,6 +410,8 @@ func NewScript(scriptSig []byte, scriptPubKey []byte, txidx int, tx *btcwire.Msg } } + // Parse flags. + bip16 := flags&ScriptBip16 == ScriptBip16 if bip16 && isScriptHash(m.scripts[1]) { // if we are pay to scripthash then we only accept input // scripts that push data @@ -393,6 +420,9 @@ func NewScript(scriptSig []byte, scriptPubKey []byte, txidx int, tx *btcwire.Msg } m.bip16 = true } + if flags&ScriptCanonicalSignatures == ScriptCanonicalSignatures { + m.der = true + } m.tx = *tx m.txidx = txidx @@ -964,19 +994,39 @@ func signatureScriptCustomReader(reader io.Reader, tx *btcwire.MsgTx, idx int, // // 0x30 0x02 r 0x02 s func sigDER(r, s *big.Int) []byte { + // In DER format, a leading 0x00 octet must be prepended to + // the byte slice so it cannot be interpreted as a negative + // big-endian number. This is only done if the sign bit on + // the first byte is set. + var rb, sb []byte + if r.Bytes()[0]&0x80 != 0 { + paddedBytes := make([]byte, len(r.Bytes())+1) + copy(paddedBytes[1:], r.Bytes()) + rb = paddedBytes + } else { + rb = r.Bytes() + } + if s.Bytes()[0]&0x80 != 0 { + paddedBytes := make([]byte, len(s.Bytes())+1) + copy(paddedBytes[1:], s.Bytes()) + sb = paddedBytes + } else { + sb = s.Bytes() + } + // total length of returned signature is 1 byte for each magic and // length (6 total), plus lengths of r and s - length := 6 + len(r.Bytes()) + len(s.Bytes()) + length := 6 + len(rb) + len(sb) b := make([]byte, length, length) b[0] = 0x30 b[1] = byte(length - 2) b[2] = 0x02 - b[3] = byte(len(r.Bytes())) - offset := copy(b[4:], r.Bytes()) + 4 + b[3] = byte(len(rb)) + offset := copy(b[4:], rb) + 4 b[offset] = 0x02 - b[offset+1] = byte(len(s.Bytes())) - copy(b[offset+2:], s.Bytes()) + b[offset+1] = byte(len(sb)) + copy(b[offset+2:], sb) return b } diff --git a/script_test.go b/script_test.go index 0caee16b..3962650b 100644 --- a/script_test.go +++ b/script_test.go @@ -20,6 +20,7 @@ type txTest struct { pkScript []byte // output script of previous tx idx int // tx idx to be run. bip16 bool // is bip16 active? + canonicalSigs bool // should signatures be validated as canonical? parseErr error // failure of NewScript err error // Failure of Executre shouldFail bool // Execute should fail with nonspecified error. @@ -566,6 +567,178 @@ var txTests = []txTest{ SigOps: 1, }, }, + txTest{ + name: "Non-canonical signature: R value negative", + tx: &btcwire.MsgTx{ + Version: 1, + TxIn: []*btcwire.TxIn{ + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash([32]byte{ + 0xfe, 0x15, 0x62, 0xc4, + 0x8b, 0x3a, 0xa6, 0x37, + 0x3f, 0x42, 0xe9, 0x61, + 0x51, 0x89, 0xcf, 0x73, + 0x32, 0xd7, 0x33, 0x5c, + 0xbe, 0xa7, 0x80, 0xbe, + 0x69, 0x6a, 0xc6, 0xc6, + 0x50, 0xfd, 0xda, 0x4a, + }), + Index: 1, + }, + SignatureScript: []byte{ + btcscript.OP_DATA_71, + 0x30, 0x44, 0x02, 0x20, 0xa0, + 0x42, 0xde, 0xe5, 0x52, 0x6b, + 0xf2, 0x29, 0x4d, 0x3f, 0x3e, + 0xb9, 0x5a, 0xa7, 0x73, 0x19, + 0xd3, 0xff, 0x56, 0x7b, 0xcf, + 0x36, 0x46, 0x07, 0x0c, 0x81, + 0x12, 0x33, 0x01, 0xca, 0xce, + 0xa9, 0x02, 0x20, 0xea, 0x48, + 0xae, 0x58, 0xf5, 0x54, 0x10, + 0x96, 0x3f, 0xa7, 0x03, 0xdb, + 0x56, 0xf0, 0xba, 0xb2, 0x70, + 0xb1, 0x08, 0x22, 0xc5, 0x1c, + 0x68, 0x02, 0x6a, 0x97, 0x5c, + 0x7d, 0xae, 0x11, 0x2e, 0x4f, + 0x01, + btcscript.OP_DATA_65, + 0x04, 0x49, 0x45, 0x33, 0x18, + 0xbd, 0x5e, 0xcf, 0xea, 0x5f, + 0x86, 0x32, 0x8c, 0x6d, 0x8e, + 0xd4, 0x12, 0xb4, 0xde, 0x2c, + 0xab, 0xd7, 0xb8, 0x56, 0x51, + 0x2f, 0x8c, 0xb7, 0xfd, 0x25, + 0xf6, 0x03, 0xb0, 0x55, 0xc5, + 0xdf, 0xe6, 0x22, 0x4b, 0xc4, + 0xfd, 0xbb, 0x6a, 0x7a, 0xa0, + 0x58, 0xd7, 0x5d, 0xad, 0x92, + 0x99, 0x45, 0x4f, 0x62, 0x1a, + 0x95, 0xb4, 0xb0, 0x21, 0x0e, + 0xc4, 0x09, 0x2b, 0xe5, 0x27, + }, + Sequence: 4294967295, + }, + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash([32]byte{ + 0x2a, 0xc7, 0xee, 0xf8, + 0xa9, 0x62, 0x2d, 0xda, + 0xec, 0x18, 0x3b, 0xba, + 0xa9, 0x92, 0xb0, 0x7a, + 0x70, 0x3b, 0x48, 0x86, + 0x27, 0x9c, 0x46, 0xac, + 0x25, 0xeb, 0x91, 0xec, + 0x4c, 0x86, 0xd2, 0x9c, + }), + Index: 1, + }, + SignatureScript: []byte{ + btcscript.OP_DATA_71, + 0x30, 0x44, 0x02, 0x20, 0xc3, + 0x02, 0x3b, 0xed, 0x85, 0x0d, + 0x94, 0x27, 0x8e, 0x06, 0xd2, + 0x37, 0x92, 0x21, 0x55, 0x28, + 0xdd, 0xdb, 0x63, 0xa4, 0xb6, + 0x88, 0x33, 0x92, 0x06, 0xdd, + 0xf9, 0xee, 0x72, 0x97, 0xa3, + 0x08, 0x02, 0x20, 0x25, 0x00, + 0x42, 0x8b, 0x26, 0x36, 0x45, + 0x54, 0xcb, 0x11, 0xd3, 0x3e, + 0x85, 0x35, 0x23, 0x49, 0x65, + 0x82, 0x8e, 0x33, 0x6e, 0x1a, + 0x4a, 0x72, 0x73, 0xeb, 0x5b, + 0x8d, 0x1d, 0xd7, 0x02, 0xcc, + 0x01, + btcscript.OP_DATA_65, + 0x04, 0x49, 0x5c, 0x8f, 0x66, + 0x90, 0x0d, 0xb7, 0x62, 0x69, + 0x0b, 0x54, 0x49, 0xa1, 0xf4, + 0xe7, 0xc2, 0xed, 0x1f, 0x4b, + 0x34, 0x70, 0xfd, 0x42, 0x79, + 0x68, 0xa1, 0x31, 0x76, 0x0c, + 0x25, 0xf9, 0x12, 0x63, 0xad, + 0x51, 0x73, 0x8e, 0x19, 0xb6, + 0x07, 0xf5, 0xcf, 0x5f, 0x94, + 0x27, 0x4a, 0x8b, 0xbc, 0x74, + 0xba, 0x4b, 0x56, 0x0c, 0xe0, + 0xb3, 0x08, 0x8f, 0x7f, 0x5c, + 0x5f, 0xcf, 0xd6, 0xa0, 0x4b, + }, + Sequence: 4294967295, + }, + }, + TxOut: []*btcwire.TxOut{ + &btcwire.TxOut{ + Value: 630320000, + PkScript: []byte{ + btcscript.OP_DUP, + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0x43, 0xdc, 0x32, 0x1b, 0x66, + 0x00, 0x51, 0x1f, 0xe0, 0xa9, + 0x6a, 0x97, 0xc2, 0x59, 0x3a, + 0x90, 0x54, 0x29, 0x74, 0xd6, + btcscript.OP_EQUALVERIFY, + btcscript.OP_CHECKSIG, + }, + }, + &btcwire.TxOut{ + Value: 100000181, + PkScript: []byte{ + btcscript.OP_DUP, + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0xa4, 0x05, 0xea, 0x18, 0x09, + 0x14, 0xa9, 0x11, 0xd0, 0xb8, + 0x07, 0x99, 0x19, 0x2b, 0x0b, + 0x84, 0xae, 0x80, 0x1e, 0xbd, + btcscript.OP_EQUALVERIFY, + btcscript.OP_CHECKSIG, + }, + }, + &btcwire.TxOut{ + Value: 596516343, + PkScript: []byte{ + btcscript.OP_DUP, + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0x24, 0x56, 0x76, 0x45, 0x4f, + 0x6f, 0xff, 0x28, 0x88, 0x39, + 0x47, 0xea, 0x70, 0x23, 0x86, + 0x9b, 0x8a, 0x71, 0xa3, 0x05, + btcscript.OP_EQUALVERIFY, + btcscript.OP_CHECKSIG, + }, + }, + }, + LockTime: 0, + }, + // Test input 0 + pkScript: []byte{ + btcscript.OP_DUP, + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0xfd, 0xf6, 0xea, 0xe7, 0x10, + 0xa0, 0xc4, 0x49, 0x7a, 0x8d, + 0x0f, 0xd2, 0x9a, 0xf6, 0x6b, + 0xac, 0x94, 0xaf, 0x6c, 0x98, + btcscript.OP_EQUALVERIFY, + btcscript.OP_CHECKSIG, + }, + idx: 0, + canonicalSigs: true, + shouldFail: true, + nSigOps: 1, + scriptInfo: btcscript.ScriptInfo{ + PkScriptClass: btcscript.PubKeyHashTy, + NumInputs: 2, + ExpectedInputs: 2, + SigOps: 1, + }, + }, + // tx 51bf528ecf3c161e7c021224197dbe84f9a8564212f6207baa014c01a1668e1e // first instance of an AnyoneCanPay signature in the blockchain txTest{ @@ -1265,9 +1438,16 @@ var txTests = []txTest{ // nothing in the blockchain that we have yet seen uses them, making it hard // to confirm we implemented the spec correctly. func testTx(t *testing.T, test txTest) { + var flags btcscript.ScriptFlags + if test.bip16 { + flags |= btcscript.ScriptBip16 + } + if test.canonicalSigs { + flags |= btcscript.ScriptCanonicalSignatures + } engine, err := btcscript.NewScript( test.tx.TxIn[test.idx].SignatureScript, test.pkScript, - test.idx, test.tx, test.bip16) + test.idx, test.tx, flags) if err != nil { if err != test.parseErr { t.Errorf("Failed to parse %s: got \"%v\" expected "+ @@ -1983,7 +2163,7 @@ func TestBadPC(t *testing.T) { for _, test := range pcTests { engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript, - pkScript, 0, tx, false) + pkScript, 0, tx, 0) if err != nil { t.Errorf("Failed to create script: %v", err) } @@ -2053,7 +2233,7 @@ func TestCheckErrorCondition(t *testing.T) { } engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript, pkScript, - 0, tx, false) + 0, tx, 0) if err != nil { t.Errorf("failed to create script: %v", err) } @@ -2460,10 +2640,11 @@ nexttest: } // Validate tx input scripts + scriptFlags := btcscript.ScriptBip16 | btcscript.ScriptCanonicalSignatures for j, txin := range tx.TxIn { engine, err := btcscript.NewScript(txin.SignatureScript, SigScriptTests[i].inputs[j].txout.PkScript, - j, tx, true) + j, tx, scriptFlags) if err != nil { t.Errorf("cannot create script vm for test %v: %v", SigScriptTests[i].name, err) diff --git a/test_coverage.txt b/test_coverage.txt index 0e9376e9..0ac26ed4 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -4,17 +4,17 @@ github.com/conformal/btcscript/script.go Script.Step 100.00% (37/37) github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (30/30) github.com/conformal/btcscript/script.go CalcScriptInfo 100.00% (25/25) github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23) +github.com/conformal/btcscript/script.go sigDER 100.00% (22/22) +github.com/conformal/btcscript/script.go NewScript 100.00% (21/21) github.com/conformal/btcscript/stack.go asInt 100.00% (21/21) -github.com/conformal/btcscript/script.go NewScript 100.00% (18/18) github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (15/15) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (14/14) +github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) -github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) -github.com/conformal/btcscript/script.go sigDER 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) @@ -140,8 +140,8 @@ github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.21% (55/56) -github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) +github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.28% (57/58) +github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.55% (28/29) github.com/conformal/btcscript/script.go calcScriptHash 82.05% (32/39) github.com/conformal/btcscript/script.go Script.CheckErrorCondition 78.57% (11/14) github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) @@ -149,5 +149,5 @@ github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/script.go IsPushOnlyScript 0.00% (0/4) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript --------------------------- 96.52% (970/1005) +github.com/conformal/btcscript --------------------------- 96.58% (989/1024) From b0899204d9e33dd0270c9993e2c65ac7e5631514 Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Sun, 27 Oct 2013 19:42:45 -0400 Subject: [PATCH 055/174] Update NewScript example after API change. This change updates the doc.go documentation file with the correct use of the new (since 8eead5217d6af35b9def1558fc0529bac3af5067) API used for passing additional options when creating new script engines. Spotted by davec@ --- doc.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc.go b/doc.go index ebca20c6..4b50547f 100644 --- a/doc.go +++ b/doc.go @@ -44,8 +44,12 @@ engine to validate a transaction. func ValidateTx(tx *btcwire.MsgTx, txIdx int, txIn *btcwire.MsgTx, txInIdx int, timestamp time.Time) { pkScript := txIn.TxOut[txInIdx].PkScript sigScript := tx.txIn[TxIdx] + var flags btcscript.ScriptFlags + if timestamp.After(btcscript.Bip16Activation) { + flags |= btcscript.ScriptBip16 + } engine, err := btcscript.NewScript(sigScript, pkScript, txInIdx, - tx, timestamp.After(btcscript.Bip16Activation)) + tx, flags) return engine.Execute() } From e8321441afb7491172919704278059f7c2991920 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Wed, 6 Nov 2013 00:10:16 +0000 Subject: [PATCH 056/174] add a stringer for ScriptClass --- script.go | 18 ++++++++++++++++++ script_test.go | 47 +++++++++++++++++++++++++++++++++++++++++++++++ test_coverage.txt | 21 +++++++++++---------- 3 files changed, 76 insertions(+), 10 deletions(-) diff --git a/script.go b/script.go index 9aa814bb..a275aef4 100644 --- a/script.go +++ b/script.go @@ -146,6 +146,24 @@ const ( NonStandardTy // None of the above. ) +var scriptClassToName = []string{ + PubKeyTy: "pubkey", + PubKeyHashTy: "pubkeyhash", + ScriptHashTy: "scripthash", + MultiSigTy: "multisig", + NonStandardTy: "nonstandard", +} + +// String implements the Stringer interface by returning the name of +// the enum script class. If the enum is invalid then "Invalid" will be +// returned. +func (t ScriptClass) String() string { + if int(t) > len(scriptClassToName) || int(t) < 0 { + return "Invalid" + } + return scriptClassToName[t] +} + // Script is the virtual machine that executes btcscripts. type Script struct { scripts [][]parsedOpcode diff --git a/script_test.go b/script_test.go index 3962650b..7371761c 100644 --- a/script_test.go +++ b/script_test.go @@ -2664,3 +2664,50 @@ nexttest: } } } + +var classStringifyTests = []struct{ + name string + scriptclass btcscript.ScriptClass + stringed string +}{ + { + name: "pubkey", + scriptclass: btcscript.PubKeyTy, + stringed: "pubkey", + }, + { + name: "pubkeyhash", + scriptclass: btcscript.PubKeyHashTy, + stringed: "pubkeyhash", + }, + { + name: "scripthash", + scriptclass: btcscript.ScriptHashTy, + stringed: "scripthash", + }, + { + name: "multisigty", + scriptclass: btcscript.MultiSigTy, + stringed: "multisig", + }, + { + name: "nonstandard", + scriptclass: btcscript.NonStandardTy, + stringed: "nonstandard", + }, + { + name: "broken", + scriptclass: btcscript.ScriptClass(255), + stringed: "Invalid", + }, +} + +func TestStringifyClass(t *testing.T) { + for _, test := range classStringifyTests { + typeString := test.scriptclass.String() + if typeString != test.stringed { + t.Errorf("%s: got \"%s\" expected \"%s\"", test.name, + typeString, test.stringed) + } + } +} diff --git a/test_coverage.txt b/test_coverage.txt index 0ac26ed4..f0709775 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -84,24 +84,24 @@ github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) -github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) -github.com/conformal/btcscript/script.go setStack 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) -github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) +github.com/conformal/btcscript/script.go setStack 100.00% (3/3) +github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) -github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) +github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) +github.com/conformal/btcscript/script.go ScriptClass.String 100.00% (3/3) +github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/conformal/btcscript/address.go ScriptToAddrHash 100.00% (2/2) github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) +github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/script.go PayToPubKeyHashScript 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) -github.com/conformal/btcscript/script.go PayToPubKeyHashScript 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/conformal/btcscript/address.go ScriptToAddrHash 100.00% (2/2) -github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) @@ -131,6 +131,7 @@ github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) @@ -149,5 +150,5 @@ github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/script.go IsPushOnlyScript 0.00% (0/4) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript --------------------------- 96.58% (989/1024) +github.com/conformal/btcscript --------------------------- 96.59% (992/1027) From 3aaafbd7faafcb5a5b5e5ec4f208224df3abbb6e Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Thu, 7 Nov 2013 17:09:22 +0000 Subject: [PATCH 057/174] handle op_checksig with an empty signature on the stack. Crash found by jy-p, fix by me. --- opcode.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/opcode.go b/opcode.go index 21a4ee18..2ef4444e 100644 --- a/opcode.go +++ b/opcode.go @@ -1662,6 +1662,13 @@ func opcodeCheckSig(op *parsedOpcode, s *Script) error { return err } + // Signature actually needs needs to be longer than this, but we need + // at least 1 byte for the below. btcec will check full length upon + // parsing the signature. + if len(sigStr) < 1 { + return errors.New("Short signature") + } + // Trim off hashtype from the signature string. hashType := sigStr[len(sigStr)-1] sigStr = sigStr[:len(sigStr)-1] From f0e7011b6f62c067bc6719f810e30c7bb03c1908 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Thu, 7 Nov 2013 17:32:11 +0000 Subject: [PATCH 058/174] fix previous. test patch, commit patch. Not the other way around, dumbass. --- opcode.go | 1 + 1 file changed, 1 insertion(+) diff --git a/opcode.go b/opcode.go index 2ef4444e..80d83aee 100644 --- a/opcode.go +++ b/opcode.go @@ -11,6 +11,7 @@ import ( "crypto/sha1" "crypto/sha256" "encoding/binary" + "errors" "fmt" "github.com/conformal/btcec" "github.com/conformal/btcwire" From f4a6449ad3b90d0c830bf2895b83ced8d5fb91e9 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Thu, 7 Nov 2013 18:22:48 +0000 Subject: [PATCH 059/174] Actually just fail the opcode, not returning an error. should fix some crazy script on testnet. --- opcode.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opcode.go b/opcode.go index 80d83aee..f85bc999 100644 --- a/opcode.go +++ b/opcode.go @@ -11,7 +11,6 @@ import ( "crypto/sha1" "crypto/sha256" "encoding/binary" - "errors" "fmt" "github.com/conformal/btcec" "github.com/conformal/btcwire" @@ -1667,7 +1666,8 @@ func opcodeCheckSig(op *parsedOpcode, s *Script) error { // at least 1 byte for the below. btcec will check full length upon // parsing the signature. if len(sigStr) < 1 { - return errors.New("Short signature") + s.dstack.PushBool(false) + return nil } // Trim off hashtype from the signature string. From 1ca389aa3d063d813273d290a5102d6d088b4dfb Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 14 Nov 2013 11:13:58 -0600 Subject: [PATCH 060/174] Go fmt. --- script.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/script.go b/script.go index a275aef4..1ca6bd7d 100644 --- a/script.go +++ b/script.go @@ -147,10 +147,10 @@ const ( ) var scriptClassToName = []string{ - PubKeyTy: "pubkey", - PubKeyHashTy: "pubkeyhash", - ScriptHashTy: "scripthash", - MultiSigTy: "multisig", + PubKeyTy: "pubkey", + PubKeyHashTy: "pubkeyhash", + ScriptHashTy: "scripthash", + MultiSigTy: "multisig", NonStandardTy: "nonstandard", } From e2770d3691ee85c10ec40cb4eecbb3ecf97127cc Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 14 Nov 2013 14:39:57 -0600 Subject: [PATCH 061/174] Go fmt. --- script_test.go | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/script_test.go b/script_test.go index 7371761c..fffa00cf 100644 --- a/script_test.go +++ b/script_test.go @@ -2665,40 +2665,35 @@ nexttest: } } -var classStringifyTests = []struct{ - name string +var classStringifyTests = []struct { + name string scriptclass btcscript.ScriptClass - stringed string + stringed string }{ { - name: "pubkey", + name: "pubkey", scriptclass: btcscript.PubKeyTy, - stringed: "pubkey", + stringed: "pubkey", }, { - name: "pubkeyhash", + name: "pubkeyhash", scriptclass: btcscript.PubKeyHashTy, - stringed: "pubkeyhash", + stringed: "pubkeyhash", }, { - name: "scripthash", + name: "scripthash", scriptclass: btcscript.ScriptHashTy, - stringed: "scripthash", + stringed: "scripthash", }, { - name: "multisigty", + name: "multisigty", scriptclass: btcscript.MultiSigTy, - stringed: "multisig", + stringed: "multisig", }, { - name: "nonstandard", - scriptclass: btcscript.NonStandardTy, - stringed: "nonstandard", - }, - { - name: "broken", + name: "broken", scriptclass: btcscript.ScriptClass(255), - stringed: "Invalid", + stringed: "Invalid", }, } From 80e8c589d87ab0b6a3e5361324cefb50a7358298 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 14 Nov 2013 14:42:44 -0600 Subject: [PATCH 062/174] Bring back nonstand script class stringer test. --- script_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/script_test.go b/script_test.go index fffa00cf..1e96f9b4 100644 --- a/script_test.go +++ b/script_test.go @@ -2670,6 +2670,11 @@ var classStringifyTests = []struct { scriptclass btcscript.ScriptClass stringed string }{ + { + name: "nonstandardty", + scriptclass: btcscript.NonStandardTy + stringed: "nonstandard", + }, { name: "pubkey", scriptclass: btcscript.PubKeyTy, From 8550b1168527e51c261e11ec58deb3fb22fcccf8 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 14 Nov 2013 14:43:40 -0600 Subject: [PATCH 063/174] Fix missing comma. --- script_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script_test.go b/script_test.go index 1e96f9b4..2f38e451 100644 --- a/script_test.go +++ b/script_test.go @@ -2672,7 +2672,7 @@ var classStringifyTests = []struct { }{ { name: "nonstandardty", - scriptclass: btcscript.NonStandardTy + scriptclass: btcscript.NonStandardTy, stringed: "nonstandard", }, { From c33bd15df2cce3edfa021fbe67b4e56192d180f5 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 14 Nov 2013 11:14:25 -0600 Subject: [PATCH 064/174] Add a new func CalcMultiSigStats. This commit adds a new function to extract the number of pulic keys and number of signatures from a multi-signature script. ok @owainga --- script.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/script.go b/script.go index 1ca6bd7d..beef9bbd 100644 --- a/script.go +++ b/script.go @@ -1144,3 +1144,28 @@ func CalcScriptInfo(sigscript, pkscript []byte, bip16 bool) (*ScriptInfo, error) return si, nil } + +// CalcMultiSigStats returns the number of public keys and signatures from +// a multi-signature transaction script. The passed script MUST already be +// known to be a multi-signature script. +func CalcMultiSigStats(script []byte) (int, int, error) { + pops, err := parseScript(script) + if err != nil { + return 0, 0, err + } + + // A multi-signature script is of the pattern: + // NUM_SIGS PUBKEY PUBKEY PUBKEY... NUM_PUBKEYS OP_CHECKMULTISIG + // Therefore the number of signatures is the oldest item on the stack + // and the number of pubkeys is the 2nd to last. Also, the absolute + // minimum for a multi-signature script is 1 pubkey, so at least 4 + // items must be on the stack per: + // OP_1 PUBKEY OP_1 OP_CHECKMULTISIG + if len(pops) < 4 { + return 0, 0, StackErrUnderflow + } + + numSigs := int(pops[0].opcode.value - (OP_1 - 1)) + numPubKeys := int(pops[len(pops)-2].opcode.value - (OP_1 - 1)) + return numPubKeys, numSigs, nil +} From cfc2a4cc76e64ae18f898195c1b11d82b6321d33 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 14 Nov 2013 15:05:20 -0600 Subject: [PATCH 065/174] Add support for nulldata standard scripts. This commit adds the new standard script type for empty, but data carrying and provably prunable transaction scripts. Closes #2. ok @owainga --- script.go | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/script.go b/script.go index beef9bbd..fe2c2ab8 100644 --- a/script.go +++ b/script.go @@ -139,19 +139,21 @@ type ScriptClass byte // Classes of script payment known about in the blockchain. const ( - PubKeyTy ScriptClass = iota // Pay pubkey. + NonStandardTy ScriptClass = iota // None of the recognized forms. + PubKeyTy // Pay pubkey. PubKeyHashTy // Pay pubkey hash. ScriptHashTy // Pay to script hash. MultiSigTy // Multi signature. - NonStandardTy // None of the above. + NullDataTy // Empty data-only (provably prunable). ) var scriptClassToName = []string{ + NonStandardTy: "nonstandard", PubKeyTy: "pubkey", PubKeyHashTy: "pubkeyhash", ScriptHashTy: "scripthash", MultiSigTy: "multisig", - NonStandardTy: "nonstandard", + NullDataTy: "nulldata", } // String implements the Stringer interface by returning the name of @@ -251,6 +253,22 @@ func isMultiSig(pops []parsedOpcode) bool { return true } +// isNullData returns true if the passed script is a null data transaction, +// false otherwise. +func isNullData(pops []parsedOpcode) bool { + // A nulldata transaction is either a single OP_RETURN or an + // OP_RETURN SMALLDATA (where SMALLDATA is a push data up to 80 bytes). + l := len(pops) + if l == 1 && pops[0].opcode.value == OP_RETURN { + return true + } + + return l == 2 && + pops[0].opcode.value == OP_RETURN && + pops[1].opcode.value <= OP_PUSHDATA4 && + len(pops[1].data) <= 80 +} + // isPushOnly returns true if the script only pushes data, false otherwise. func isPushOnly(pops []parsedOpcode) bool { // technically we cheat here, we don't look at opcodes @@ -297,6 +315,8 @@ func typeOfScript(pops []parsedOpcode) ScriptClass { return ScriptHashTy } else if isMultiSig(pops) { return MultiSigTy + } else if isNullData(pops) { + return NullDataTy } return NonStandardTy @@ -1070,10 +1090,11 @@ func expectedInputs(pops []parsedOpcode, class ScriptClass) int { // expected. typoeOfScript already checked this so that we know // it'll be one of OP_1 - OP_16. return int(pops[0].opcode.value - (OP_1 - 1)) + case NullDataTy: + fallthrough default: return -1 } - } type ScriptInfo struct { From d4c5b3d04d49097c0f17c81d29c183f4a1593f6c Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 14 Nov 2013 15:07:35 -0600 Subject: [PATCH 066/174] Add tests for new nulldata standard script type. --- script_test.go | 77 +++++++++++++++++++++++++++++++++++++++++++- test_coverage.txt | 81 ++++++++++++++++++++++++----------------------- 2 files changed, 117 insertions(+), 41 deletions(-) diff --git a/script_test.go b/script_test.go index 2f38e451..d5f45679 100644 --- a/script_test.go +++ b/script_test.go @@ -2007,7 +2007,77 @@ var scriptTypeTests = []scriptTypeTest{ }, scripttype: btcscript.ScriptHashTy, }, - // The next few are almost multisig (it is the more complex script type) + // Nulldata with no data at all. + scriptTypeTest{ + name: "nulldata", + script: []byte{ + btcscript.OP_RETURN, + }, + scripttype: btcscript.NullDataTy, + }, + // Nulldata with small data. + scriptTypeTest{ + name: "nulldata2", + script: []byte{ + btcscript.OP_RETURN, + btcscript.OP_DATA_8, + 0x04, 0x67, 0x08, 0xaf, 0xdb, 0x0f, 0xe5, 0x54, + }, + scripttype: btcscript.NullDataTy, + }, + // Nulldata with max allowed data. + scriptTypeTest{ + name: "nulldata3", + script: []byte{ + btcscript.OP_RETURN, + btcscript.OP_PUSHDATA1, + 0x50, + 0x04, 0x67, 0x08, 0xaf, 0xdb, 0x0f, 0xe5, 0x54, + 0x82, 0x71, 0x96, 0x7f, 0x1a, 0x67, 0x13, 0x0b, + 0x71, 0x05, 0xcd, 0x6a, 0x82, 0x8e, 0x03, 0x90, + 0x9a, 0x67, 0x96, 0x2e, 0x0e, 0xa1, 0xf6, 0x1d, + 0xeb, 0x64, 0x9f, 0x6b, 0xc3, 0xf4, 0xce, 0xf3, + 0x80, 0x46, 0x78, 0xaf, 0xdb, 0x0f, 0xe5, 0x54, + 0x82, 0x71, 0x96, 0x7f, 0x1a, 0x67, 0x13, 0x0b, + 0x71, 0x05, 0xcd, 0x6a, 0x82, 0x8e, 0x03, 0x90, + 0x9a, 0x67, 0x96, 0x2e, 0x0e, 0xa1, 0xf6, 0x1d, + 0xeb, 0x64, 0x9f, 0x6b, 0xc3, 0xf4, 0xce, 0xf3, + }, + scripttype: btcscript.NullDataTy, + }, + // Nulldata with more than max allowed data (so therefore nonstandard) + scriptTypeTest{ + name: "nulldata4", + script: []byte{ + btcscript.OP_RETURN, + btcscript.OP_PUSHDATA1, + 0x51, + 0x04, 0x67, 0x08, 0xaf, 0xdb, 0x0f, 0xe5, 0x54, + 0x82, 0x71, 0x96, 0x7f, 0x1a, 0x67, 0x13, 0x0b, + 0x71, 0x05, 0xcd, 0x6a, 0x82, 0x8e, 0x03, 0x90, + 0x9a, 0x67, 0x96, 0x2e, 0x0e, 0xa1, 0xf6, 0x1d, + 0xeb, 0x64, 0x9f, 0x6b, 0xc3, 0xf4, 0xce, 0xf3, + 0x80, 0x46, 0x78, 0xaf, 0xdb, 0x0f, 0xe5, 0x54, + 0x82, 0x71, 0x96, 0x7f, 0x1a, 0x67, 0x13, 0x0b, + 0x71, 0x05, 0xcd, 0x6a, 0x82, 0x8e, 0x03, 0x90, + 0x9a, 0x67, 0x96, 0x2e, 0x0e, 0xa1, 0xf6, 0x1d, + 0xeb, 0x64, 0x9f, 0x6b, 0xc3, 0xf4, 0xce, 0xf3, + 0x08, + }, + scripttype: btcscript.NonStandardTy, + }, + // Almost nulldata, but add an additional opcode after the data to make + // it nonstandard. + scriptTypeTest{ + name: "nulldata5", + script: []byte{ + btcscript.OP_RETURN, + btcscript.OP_DATA_1, + 0x04, + btcscript.OP_TRUE, + }, + scripttype: btcscript.NonStandardTy, + }, // The next few are almost multisig (it is the more complex script type) // but with various changes to make it fail. scriptTypeTest{ // multisig but funny nsigs.. @@ -2695,6 +2765,11 @@ var classStringifyTests = []struct { scriptclass: btcscript.MultiSigTy, stringed: "multisig", }, + { + name: "nulldataty", + scriptclass: btcscript.NullDataTy, + stringed: "nulldata", + }, { name: "broken", scriptclass: btcscript.ScriptClass(255), diff --git a/test_coverage.txt b/test_coverage.txt index f0709775..b57291c4 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -8,17 +8,18 @@ github.com/conformal/btcscript/script.go sigDER 100.00% (22/22) github.com/conformal/btcscript/script.go NewScript 100.00% (21/21) github.com/conformal/btcscript/stack.go asInt 100.00% (21/21) github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (15/15) -github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (14/14) -github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) -github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) +github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) +github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) +github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) @@ -27,36 +28,33 @@ github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) -github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) +github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/script.go unparseScript 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) -github.com/conformal/btcscript/script.go unparseScript 100.00% (7/7) +github.com/conformal/btcscript/script.go typeOfScript 100.00% (7/7) +github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) -github.com/conformal/btcscript/script.go typeOfScript 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) -github.com/conformal/btcscript/script.go expectedInputs 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) @@ -64,10 +62,12 @@ github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) -github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) +github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) @@ -77,43 +77,43 @@ github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) +github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) +github.com/conformal/btcscript/script.go isNullData 100.00% (4/4) github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) -github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) -github.com/conformal/btcscript/script.go setStack 100.00% (3/3) -github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) -github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) github.com/conformal/btcscript/script.go ScriptClass.String 100.00% (3/3) +github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) +github.com/conformal/btcscript/script.go setStack 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) +github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/conformal/btcscript/address.go ScriptToAddrHash 100.00% (2/2) -github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) +github.com/conformal/btcscript/address.go ScriptToAddrHash 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) github.com/conformal/btcscript/script.go PayToPubKeyHashScript 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) +github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) +github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) +github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) +github.com/conformal/btcscript/log.go init 100.00% (1/1) github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) -github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) github.com/conformal/btcscript/opcode.go init 100.00% (1/1) -github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/log.go init 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) @@ -123,15 +123,15 @@ github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) @@ -142,7 +142,8 @@ github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.28% (57/58) -github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.55% (28/29) +github.com/conformal/btcscript/opcode.go opcodeCheckSig 90.62% (29/32) +github.com/conformal/btcscript/script.go expectedInputs 85.71% (6/7) github.com/conformal/btcscript/script.go calcScriptHash 82.05% (32/39) github.com/conformal/btcscript/script.go Script.CheckErrorCondition 78.57% (11/14) github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) @@ -150,5 +151,5 @@ github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/script.go IsPushOnlyScript 0.00% (0/4) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript --------------------------- 96.59% (992/1027) +github.com/conformal/btcscript --------------------------- 96.33% (998/1036) From aa3cdbe7b1d0059c5f01c60595e233a2b40a8463 Mon Sep 17 00:00:00 2001 From: Marco Peereboom Date: Wed, 6 Nov 2013 17:43:03 -0600 Subject: [PATCH 067/174] use fastsha256 --- opcode.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/opcode.go b/opcode.go index f85bc999..d93f1f8d 100644 --- a/opcode.go +++ b/opcode.go @@ -9,11 +9,11 @@ import ( "code.google.com/p/go.crypto/ripemd160" "crypto/ecdsa" "crypto/sha1" - "crypto/sha256" "encoding/binary" "fmt" "github.com/conformal/btcec" "github.com/conformal/btcwire" + "github.com/conformal/fastsha256" "github.com/davecgh/go-spew/spew" "hash" "math/big" @@ -1591,7 +1591,7 @@ func calcHash(buf []byte, hasher hash.Hash) []byte { // calculate hash160 which is ripemd160(sha256(data)) func calcHash160(buf []byte) []byte { - return calcHash(calcHash(buf, sha256.New()), ripemd160.New()) + return calcHash(calcHash(buf, fastsha256.New()), ripemd160.New()) } func opcodeRipemd160(op *parsedOpcode, s *Script) error { @@ -1620,7 +1620,7 @@ func opcodeSha256(op *parsedOpcode, s *Script) error { return err } - s.dstack.PushByteArray(calcHash(buf, sha256.New())) + s.dstack.PushByteArray(calcHash(buf, fastsha256.New())) return nil } From 58e5fd3aec94a7d9a5a5950dd3c0b63a8aba4e09 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 21 Nov 2013 09:36:58 -0600 Subject: [PATCH 068/174] Use btclog for logging. --- log.go | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/log.go b/log.go index 28faf744..4b938bd4 100644 --- a/log.go +++ b/log.go @@ -6,14 +6,14 @@ package btcscript import ( "errors" - "github.com/conformal/seelog" + "github.com/conformal/btclog" "io" ) // log is a logger that is initialized with no output filters. This // means the package will not perform any logging by default until the caller // requests it. -var log seelog.LoggerInterface +var log btclog.Logger // The default amount of logging is none. func init() { @@ -23,26 +23,31 @@ func init() { // DisableLog disables all library log output. Logging output is disabled // by default until either UseLogger or SetLogWriter are called. func DisableLog() { - log = seelog.Disabled + log = btclog.Disabled } // UseLogger uses a specified Logger to output package logging info. // This should be used in preference to SetLogWriter if the caller is also -// using seelog. -func UseLogger(logger seelog.LoggerInterface) { +// using btclog. +func UseLogger(logger btclog.Logger) { log = logger } // SetLogWriter uses a specified io.Writer to output package logging info. // This allows a caller to direct package logging output without needing a -// dependency on seelog. If the caller is also using seelog, UseLogger should +// dependency on seelog. If the caller is also using btclog, UseLogger should // be used instead. -func SetLogWriter(w io.Writer) error { +func SetLogWriter(w io.Writer, level string) error { if w == nil { return errors.New("nil writer") } - l, err := seelog.LoggerFromWriterWithMinLevel(w, seelog.TraceLvl) + lvl, ok := btclog.LogLevelFromString(level) + if !ok { + return errors.New("invalid log level") + } + + l, err := btclog.NewLoggerFromWriter(w, lvl) if err != nil { return err } From 18576ab105e9787a17490e230e052291c4eca273 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Tue, 10 Dec 2013 18:01:11 -0600 Subject: [PATCH 069/174] Add support for TravisCI. Also add TravisCI build status badge to README.md. --- .travis.yml | 3 +++ README.md | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..ae71c02f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,3 @@ +language: go +go: release +install: go get -d -t -v ./... diff --git a/README.md b/README.md index bb00df62..4b14e99f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ btcscript ========= +[![Build Status](https://travis-ci.org/conformal/btcscript.png?branch=master)] +(https://travis-ci.org/conformal/btcscript) + Package btcscript implements the bitcoin transaction scripts. There is a comprehensive test suite. `test_coverage.txt` contains the current coverage statistics (generated using gocov). On a UNIX-like OS, the From c0c167cc15aa3b721c983fd775cdef7afb42de38 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Tue, 10 Dec 2013 18:25:04 -0600 Subject: [PATCH 070/174] Remove logging bits from script_test.go. The allows the tests to run without showing warning for malformed bits (which are intentionally malformed for testing purposes). Also, the tests would not compile since the new btclog backend was switched out. This commit resolves that. --- opcode_test.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/opcode_test.go b/opcode_test.go index d757463e..70349be3 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -6,12 +6,9 @@ package btcscript_test import ( "bytes" - "fmt" "github.com/conformal/btcscript" "github.com/conformal/btcwire" - "github.com/conformal/seelog" "github.com/davecgh/go-spew/spew" - "os" "testing" ) @@ -520,14 +517,6 @@ func testScript(t *testing.T, script []byte, canonical bool) (err error) { } func TestScripts(t *testing.T) { - log, err := seelog.LoggerFromWriterWithMinLevel(os.Stdout, - seelog.InfoLvl) - if err != nil { - fmt.Fprintf(os.Stderr, "failed to create logger: %v", err) - return - } - defer log.Flush() - btcscript.UseLogger(log) // for each entry in the list for i := range opcodeTests { shouldPass := opcodeTests[i].shouldPass From 4f4afedf39df65eceb4d7ca2b9b2eba4042cb49e Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Mon, 23 Dec 2013 11:03:09 -0600 Subject: [PATCH 071/174] Use the new btcec Signature.Serialize API. This commit modifies the code to use the new btcec Signature.Serialize API instead of the internal sigDER which has now been removed. This closes #3. ok @owainga --- script.go | 47 ++--------------------------------------------- 1 file changed, 2 insertions(+), 45 deletions(-) diff --git a/script.go b/script.go index fe2c2ab8..2e465b47 100644 --- a/script.go +++ b/script.go @@ -15,7 +15,6 @@ import ( "github.com/conformal/btcwire" "github.com/davecgh/go-spew/spew" "io" - "math/big" "time" ) @@ -1000,7 +999,8 @@ func signatureScriptCustomReader(reader io.Reader, tx *btcwire.MsgTx, idx int, if err != nil { return nil, fmt.Errorf("cannot sign tx input: %s", err) } - sig := append(sigDER(r, s), hashType) + ecSig := btcec.Signature{R: r, S: s} + sig := append(ecSig.Serialize(), hashType) pk := (*btcec.PublicKey)(&privkey.PublicKey) var pubkeyOpcode *parsedOpcode @@ -1025,49 +1025,6 @@ func signatureScriptCustomReader(reader io.Reader, tx *btcwire.MsgTx, idx int, return unparseScript(pops) } -// sigDER returns the ECDSA signature r, s in the DER format used by -// signature scripts. The signature does not include the appended hashtype. -// -// encoding/asn1 is broken so we hand roll this output: -// -// 0x30 0x02 r 0x02 s -func sigDER(r, s *big.Int) []byte { - // In DER format, a leading 0x00 octet must be prepended to - // the byte slice so it cannot be interpreted as a negative - // big-endian number. This is only done if the sign bit on - // the first byte is set. - var rb, sb []byte - if r.Bytes()[0]&0x80 != 0 { - paddedBytes := make([]byte, len(r.Bytes())+1) - copy(paddedBytes[1:], r.Bytes()) - rb = paddedBytes - } else { - rb = r.Bytes() - } - if s.Bytes()[0]&0x80 != 0 { - paddedBytes := make([]byte, len(s.Bytes())+1) - copy(paddedBytes[1:], s.Bytes()) - sb = paddedBytes - } else { - sb = s.Bytes() - } - - // total length of returned signature is 1 byte for each magic and - // length (6 total), plus lengths of r and s - length := 6 + len(rb) + len(sb) - b := make([]byte, length, length) - - b[0] = 0x30 - b[1] = byte(length - 2) - b[2] = 0x02 - b[3] = byte(len(rb)) - offset := copy(b[4:], rb) + 4 - b[offset] = 0x02 - b[offset+1] = byte(len(sb)) - copy(b[offset+2:], sb) - return b -} - // expectedInputs returns the number of arguments required by a script. // If the script is of unnown type such that the number can not be determined // then -1 is returned. We are an interanl function and thus assume that class From a5aaf90687aaafa6782363be478d9653d133ebcf Mon Sep 17 00:00:00 2001 From: Francis Lam Date: Thu, 2 Jan 2014 00:28:16 -0500 Subject: [PATCH 072/174] Added support to decode scripthash/multisig from pkscripts --- address.go | 44 +++++++++++++++++++++++++++++++++++--------- script.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 9 deletions(-) diff --git a/address.go b/address.go index bc76be3f..14b4fa78 100644 --- a/address.go +++ b/address.go @@ -22,16 +22,20 @@ const ( ScriptUnknown ScriptType = iota ScriptAddr ScriptPubKey + ScriptPayToScriptHash + ScriptMultiSig ScriptStrange ScriptGeneration ) var scriptTypeToName = []string{ - ScriptUnknown: "Unknown", - ScriptAddr: "Addr", - ScriptPubKey: "Pubkey", - ScriptStrange: "Strange", - ScriptGeneration: "Generation", // ScriptToAddrHash does not recieve enough information to identify Generation scripts. + ScriptUnknown: "Unknown", + ScriptAddr: "Addr", + ScriptPubKey: "Pubkey", + ScriptPayToScriptHash: "PayToScriptHash", + ScriptMultiSig: "MultiSig", + ScriptStrange: "Strange", + ScriptGeneration: "Generation", // ScriptToAddrHash does not recieve enough information to identify Generation scripts. } type pkformat struct { @@ -54,6 +58,7 @@ const ( scrGeneratePubkeyAddr scrPubkeyAddr scrPubkeyAddrComp + scrPayToScriptHash scrNoAddr ) @@ -83,8 +88,8 @@ func ScriptToAddrHash(script []byte) (ScriptType, []byte, error) { {ScriptPubKey, scrGeneratePubkeyAddr, 70, []pkbytes{{0, OP_DATA_69}}, false}, {ScriptPubKey, scrPubkeyAddr, 67, []pkbytes{{0, OP_DATA_65}, {66, OP_CHECKSIG}}, true}, {ScriptPubKey, scrPubkeyAddrComp, 35, []pkbytes{{0, OP_DATA_33}, {34, OP_CHECKSIG}}, true}, + {ScriptPayToScriptHash, scrPayToScriptHash, 23, []pkbytes{{0, OP_HASH160}, {1, OP_DATA_20}, {22, OP_EQUAL}}, false}, {ScriptStrange, scrNoAddr, 33, []pkbytes{{0, OP_DATA_32}}, false}, - {ScriptStrange, scrNoAddr, 33, []pkbytes{{0, OP_HASH160}, {1, OP_DATA_20}, {22, OP_EQUAL}}, false}, } return scriptToAddrHashTemplate(script, validformats) } @@ -129,9 +134,6 @@ func scriptToAddrHashTemplate(script []byte, validformats []pkformat) (ScriptTyp if script[0] == OP_0 && (len(script) <= 75 && byte(len(script)) == script[1]+2) { return ScriptStrange, nil, nil } - if script[0] == OP_HASH160 && len(script) == 23 && script[22] == OP_EQUAL { - return ScriptStrange, nil, nil - } if script[0] == OP_DATA_36 && len(script) == 37 { // Multisig ScriptSig return ScriptStrange, nil, nil @@ -165,9 +167,33 @@ func scriptToAddrHashTemplate(script []byte, validformats []pkformat) (ScriptTyp case scrPubkeyAddrComp: pubkey := script[1:34] addrhash = calcHash160(pubkey) + case scrPayToScriptHash: + addrhash = script[2:22] default: return ScriptUnknown, nil, StackErrInvalidParseType } return format.addrtype, addrhash, nil } + +// ScriptToAddrHashes extracts multiply 20-byte public key hash and the type out of a PkScript +func ScriptToMultiSigAddresses(script []byte) (ScriptType, int, [][]byte, error) { + pops, err := parseScript(script) + if err != nil { + return ScriptUnknown, 0, nil, err + } + + if !isMultiSig(pops) { + return ScriptUnknown, 0, nil, StackErrUnknownAddress + } + + l := len(pops) + addrHashes := make([][]byte, l-3) + for i, pop := range pops[1 : l-2] { + addrHashes[i] = calcHash160(pop.data) + } + + reqSigs := int(pops[0].opcode.value - (OP_1 - 1)) + + return ScriptMultiSig, reqSigs, addrHashes, nil +} diff --git a/script.go b/script.go index 2e465b47..bd7dcf9a 100644 --- a/script.go +++ b/script.go @@ -1147,3 +1147,35 @@ func CalcMultiSigStats(script []byte) (int, int, error) { numPubKeys := int(pops[len(pops)-2].opcode.value - (OP_1 - 1)) return numPubKeys, numSigs, nil } + +// CalcPkScriptAddrHashes returns the type of script as well as the required +// number of signatures and the hashes of the addresses. +func CalcPkScriptAddrHashes(script []byte) (ScriptClass, int, [][]byte) { + c := GetScriptClass(script) + switch c { + case ScriptHashTy: + fallthrough + case PubKeyTy: + fallthrough + case PubKeyHashTy: + _, addrHash, err := ScriptToAddrHash(script) + if err != nil { + return NonStandardTy, 0, nil + } + return c, 1, [][]byte{addrHash} + + case MultiSigTy: + _, reqSigs, addrHashes, err := ScriptToMultiSigAddresses(script) + if err != nil { + return NonStandardTy, 0, nil + } + + return c, reqSigs, addrHashes + case NonStandardTy: + fallthrough + case NullDataTy: + fallthrough + default: + return NonStandardTy, 0, nil + } +} From 3f52f559eb6aa87e87e0249d471b1f70c88dcc20 Mon Sep 17 00:00:00 2001 From: Francis Lam Date: Thu, 2 Jan 2014 13:31:00 -0500 Subject: [PATCH 073/174] Added tests for multisig scripts and fixed comments Fixed up bad function comment headers Added a small set of tests for the ScriptToAddrHashes function to test functionality of a couple real multisig cases as well as error checking --- address.go | 7 +- address_test.go | 196 ++++++++++++++++++++++++++++++++++++++++++++++-- script.go | 2 +- 3 files changed, 195 insertions(+), 10 deletions(-) diff --git a/address.go b/address.go index 14b4fa78..5407ac12 100644 --- a/address.go +++ b/address.go @@ -176,11 +176,12 @@ func scriptToAddrHashTemplate(script []byte, validformats []pkformat) (ScriptTyp return format.addrtype, addrhash, nil } -// ScriptToAddrHashes extracts multiply 20-byte public key hash and the type out of a PkScript -func ScriptToMultiSigAddresses(script []byte) (ScriptType, int, [][]byte, error) { +// ScriptToAddrHashes extracts multiple 20-byte public key hashes +// from a MultiSig script. +func ScriptToAddrHashes(script []byte) (ScriptType, int, [][]byte, error) { pops, err := parseScript(script) if err != nil { - return ScriptUnknown, 0, nil, err + return ScriptUnknown, 0, nil, StackErrUnknownAddress } if !isMultiSig(pops) { diff --git a/address_test.go b/address_test.go index 048f8a9f..d8da48d1 100644 --- a/address_test.go +++ b/address_test.go @@ -162,13 +162,15 @@ var addressTests = []addressTest{ class: btcscript.ScriptStrange, }, {script: []byte{btcscript.OP_HASH160, btcscript.OP_DATA_20, - 0x02, 0x40, 0x05, 0xc9, 0x45, 0xd8, 0x6a, 0xc6, - 0xb0, 0x1f, 0xb0, 0x42, 0x58, 0x34, 0x5a, 0xbe, - 0xa7, 0xa8, 0x45, 0xbd, - btcscript.OP_EQUAL, // note this isn't a real tx + 0x63, 0xbc, 0xc5, 0x65, 0xf9, 0xe6, 0x8e, 0xe0, + 0x18, 0x9d, 0xd5, 0xcc, 0x67, 0xf1, 0xb0, 0xe5, + 0xf0, 0x2f, 0x45, 0xcb, + btcscript.OP_EQUAL, }, - addrhash: nil, - class: btcscript.ScriptStrange, + addrhash: []byte{0x63, 0xbc, 0xc5, 0x65, 0xf9, 0xe6, 0x8e, 0xe0, + 0x18, 0x9d, 0xd5, 0xcc, 0x67, 0xf1, 0xb0, 0xe5, + 0xf0, 0x2f, 0x45, 0xcb}, + class: btcscript.ScriptPayToScriptHash, }, {script: []byte{btcscript.OP_DATA_36, 0x02, 0x40, 0x05, 0xc9, 0x45, 0xd8, 0x6a, 0xc6, @@ -257,3 +259,185 @@ func TestStringify(t *testing.T) { } } } + +type multiSigTest struct { + script []byte + reqSigs int + addrhashes [][]byte + shouldFail error + class btcscript.ScriptType +} + +var multiSigTests = []multiSigTest{ + {script: []byte{}, + class: btcscript.ScriptUnknown, + shouldFail: btcscript.StackErrUnknownAddress, + }, + {script: []byte{btcscript.OP_DATA_65, + 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, + 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, + 0x1e, 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, + 0x2e, 0xca, 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, + 0x5c, 0xb2, 0xe0, 0xea, 0xdd, 0xfb, 0x84, 0xcc, + 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, + 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, + 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, + 0xa3, btcscript.OP_CHECKSIG}, + class: btcscript.ScriptUnknown, + shouldFail: btcscript.StackErrUnknownAddress, + }, + {script: []byte{ + btcscript.OP_1, btcscript.OP_DATA_65, + 0x04, 0xcc, 0x71, 0xeb, 0x30, 0xd6, 0x53, 0xc0, + 0xc3, 0x16, 0x39, 0x90, 0xc4, 0x7b, 0x97, 0x6f, + 0x3f, 0xb3, 0xf3, 0x7c, 0xcc, 0xdc, 0xbe, 0xdb, + 0x16, 0x9a, 0x1d, 0xfe, 0xf5, 0x8b, 0xbf, 0xbf, + 0xaf, 0xf7, 0xd8, 0xa4, 0x73, 0xe7, 0xe2, 0xe6, + 0xd3, 0x17, 0xb8, 0x7b, 0xaf, 0xe8, 0xbd, 0xe9, + 0x7e, 0x3c, 0xf8, 0xf0, 0x65, 0xde, 0xc0, 0x22, + 0xb5, 0x1d, 0x11, 0xfc, 0xdd, 0x0d, 0x34, 0x8a, + 0xc4, btcscript.OP_DATA_65, + 0x04, 0x61, 0xcb, 0xdc, 0xc5, 0x40, 0x9f, 0xb4, + 0xb4, 0xd4, 0x2b, 0x51, 0xd3, 0x33, 0x81, 0x35, + 0x4d, 0x80, 0xe5, 0x50, 0x07, 0x8c, 0xb5, 0x32, + 0xa3, 0x4b, 0xfa, 0x2f, 0xcf, 0xde, 0xb7, 0xd7, + 0x65, 0x19, 0xae, 0xcc, 0x62, 0x77, 0x0f, 0x5b, + 0x0e, 0x4e, 0xf8, 0x55, 0x19, 0x46, 0xd8, 0xa5, + 0x40, 0x91, 0x1a, 0xbe, 0x3e, 0x78, 0x54, 0xa2, + 0x6f, 0x39, 0xf5, 0x8b, 0x25, 0xc1, 0x53, 0x42, + 0xaf, btcscript.OP_2, btcscript.OP_CHECK_MULTISIG}, + class: btcscript.ScriptMultiSig, + reqSigs: 1, + addrhashes: [][]byte{ + []byte{ + 0x66, 0x0d, 0x4e, 0xf3, 0xa7, 0x43, 0xe3, 0xe6, + 0x96, 0xad, 0x99, 0x03, 0x64, 0xe5, 0x55, 0xc2, + 0x71, 0xad, 0x50, 0x4b, + }, + []byte{ + 0x64, 0x1a, 0xd5, 0x05, 0x1e, 0xdd, 0x97, 0x02, + 0x9a, 0x00, 0x3f, 0xe9, 0xef, 0xb2, 0x93, 0x59, + 0xfc, 0xee, 0x40, 0x9d, + }, + }, + }, + + // from real tx 60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1, vout 0 + {script: []byte{ + btcscript.OP_1, btcscript.OP_DATA_65, + 0x04, 0xcc, 0x71, 0xeb, 0x30, 0xd6, 0x53, 0xc0, + 0xc3, 0x16, 0x39, 0x90, 0xc4, 0x7b, 0x97, 0x6f, + 0x3f, 0xb3, 0xf3, 0x7c, 0xcc, 0xdc, 0xbe, 0xdb, + 0x16, 0x9a, 0x1d, 0xfe, 0xf5, 0x8b, 0xbf, 0xbf, + 0xaf, 0xf7, 0xd8, 0xa4, 0x73, 0xe7, 0xe2, 0xe6, + 0xd3, 0x17, 0xb8, 0x7b, 0xaf, 0xe8, 0xbd, 0xe9, + 0x7e, 0x3c, 0xf8, 0xf0, 0x65, 0xde, 0xc0, 0x22, + 0xb5, 0x1d, 0x11, 0xfc, 0xdd, 0x0d, 0x34, 0x8a, + 0xc4, btcscript.OP_DATA_65, + 0x04, 0x61, 0xcb, 0xdc, 0xc5, 0x40, 0x9f, 0xb4, + 0xb4, 0xd4, 0x2b, 0x51, 0xd3, 0x33, 0x81, 0x35, + 0x4d, 0x80, 0xe5, 0x50, 0x07, 0x8c, 0xb5, 0x32, + 0xa3, 0x4b, 0xfa, 0x2f, 0xcf, 0xde, 0xb7, 0xd7, + 0x65, 0x19, 0xae, 0xcc, 0x62, 0x77, 0x0f, 0x5b, + 0x0e, 0x4e, 0xf8, 0x55, 0x19, 0x46, 0xd8, 0xa5, + 0x40, 0x91, 0x1a, 0xbe, 0x3e, 0x78, 0x54, 0xa2, + 0x6f, 0x39, 0xf5, 0x8b, 0x25, 0xc1, 0x53, 0x42, + 0xaf, btcscript.OP_2, btcscript.OP_CHECK_MULTISIG}, + class: btcscript.ScriptMultiSig, + reqSigs: 1, + addrhashes: [][]byte{ + []byte{ + 0x66, 0x0d, 0x4e, 0xf3, 0xa7, 0x43, 0xe3, 0xe6, + 0x96, 0xad, 0x99, 0x03, 0x64, 0xe5, 0x55, 0xc2, + 0x71, 0xad, 0x50, 0x4b, + }, + []byte{ + 0x64, 0x1a, 0xd5, 0x05, 0x1e, 0xdd, 0x97, 0x02, + 0x9a, 0x00, 0x3f, 0xe9, 0xef, 0xb2, 0x93, 0x59, + 0xfc, 0xee, 0x40, 0x9d, + }, + }, + }, + + // from real tx: 691dd277dc0e90a462a3d652a1171686de49cf19067cd33c7df0392833fb986a, vout 0 + {script: []byte{ + btcscript.OP_1, btcscript.OP_DATA_65, + 0x1c, 0x22, 0x00, 0x00, 0x73, 0x53, 0x45, 0x58, + 0x57, 0x69, 0x6b, 0x69, 0x6c, 0x65, 0x61, 0x6b, + 0x73, 0x20, 0x43, 0x61, 0x62, 0x6c, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x20, 0x42, 0x61, 0x63, 0x6b, + 0x75, 0x70, 0x0a, 0x0a, 0x63, 0x61, 0x62, 0x6c, + 0x65, 0x67, 0x61, 0x74, 0x65, 0x2d, 0x32, 0x30, + 0x31, 0x30, 0x31, 0x32, 0x30, 0x34, 0x31, 0x38, + 0x31, 0x31, 0x2e, 0x37, 0x7a, 0x0a, 0x0a, 0x44, + 0x6f, btcscript.OP_DATA_65, + 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, + 0x77, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x53, + 0x61, 0x74, 0x6f, 0x73, 0x68, 0x69, 0x20, 0x4e, + 0x61, 0x6b, 0x61, 0x6d, 0x6f, 0x74, 0x6f, 0x27, + 0x73, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, + 0x61, btcscript.OP_DATA_65, + 0x64, 0x20, 0x74, 0x6f, 0x6f, 0x6c, 0x20, 0x77, + 0x68, 0x69, 0x63, 0x68, 0x0a, 0x63, 0x61, 0x6e, + 0x20, 0x62, 0x65, 0x20, 0x66, 0x6f, 0x75, 0x6e, + 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x36, 0x63, 0x35, 0x33, 0x63, 0x64, 0x39, + 0x38, 0x37, 0x31, 0x31, 0x39, 0x65, 0x66, 0x37, + 0x39, 0x37, 0x64, 0x35, 0x61, 0x64, 0x63, 0x63, + 0x64, btcscript.OP_3, btcscript.OP_CHECK_MULTISIG}, + class: btcscript.ScriptMultiSig, + reqSigs: 1, + addrhashes: [][]byte{ + []byte{ + 0x7c, 0xe9, 0x23, 0x01, 0x00, 0x75, 0x98, 0xc8, + 0xb9, 0x31, 0x5b, 0x49, 0x71, 0x21, 0xa0, 0x18, + 0x20, 0x90, 0xa3, 0x0c, + }, + []byte{ + 0x76, 0xf6, 0x95, 0x05, 0xb3, 0x9f, 0xba, 0x56, + 0x6d, 0xe8, 0x40, 0x89, 0xda, 0xd8, 0xbd, 0x35, + 0x01, 0xec, 0x47, 0xed, + }, + []byte{ + 0x7b, 0xfb, 0xfe, 0x5d, 0x66, 0x80, 0x22, 0x2e, + 0xe6, 0x38, 0xf9, 0x41, 0xdc, 0xfa, 0x61, 0x6d, + 0xd4, 0x5f, 0x11, 0xee, + }, + }, + }, +} + +func TestMultiSigs(t *testing.T) { + for i, s := range multiSigTests { + class, reqSigs, addrhashes, err := btcscript.ScriptToAddrHashes(s.script) + if s.shouldFail != nil { + if err != s.shouldFail { + t.Errorf("MultiSig test %v failed is err [%v] should be [%v]", i, err, s.shouldFail) + } + } else { + if err != nil { + t.Errorf("MultiSig test %v failed err %v", i, err) + } else { + if s.class != class { + t.Errorf("MultiSig test %v class mismatch is [%v] want [%v]", i, class, s.class) + } + if len(addrhashes) != len(s.addrhashes) { + t.Errorf("MultiSig test %v num addrhashes expected is [%d] want [%d]", i, len(addrhashes), len(s.addrhashes)) + } + if reqSigs != s.reqSigs { + t.Errorf("MultiSig test %v reqSigs expected is [%d] want [%d]", i, reqSigs, s.reqSigs) + } + for j := 0; j < len(addrhashes); j++ { + if !bytes.Equal(s.addrhashes[j], addrhashes[j]) { + t.Errorf("MultiSig test %v addrhash %d mismatch is [%v] want [%v]", i, j, addrhashes[j], s.addrhashes[j]) + } + } + } + } + + } +} diff --git a/script.go b/script.go index bd7dcf9a..0e06e00d 100644 --- a/script.go +++ b/script.go @@ -1165,7 +1165,7 @@ func CalcPkScriptAddrHashes(script []byte) (ScriptClass, int, [][]byte) { return c, 1, [][]byte{addrHash} case MultiSigTy: - _, reqSigs, addrHashes, err := ScriptToMultiSigAddresses(script) + _, reqSigs, addrHashes, err := ScriptToAddrHashes(script) if err != nil { return NonStandardTy, 0, nil } From 3a8ec0078b6a2a8fddf99a33f1e67ffb443b1b72 Mon Sep 17 00:00:00 2001 From: Francis Lam Date: Thu, 2 Jan 2014 13:50:22 -0500 Subject: [PATCH 074/174] Added another multisig test with compressed pubkey --- address_test.go | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/address_test.go b/address_test.go index d8da48d1..12b3be42 100644 --- a/address_test.go +++ b/address_test.go @@ -409,6 +409,53 @@ var multiSigTests = []multiSigTest{ }, }, }, + + // from real tx: 691dd277dc0e90a462a3d652a1171686de49cf19067cd33c7df0392833fb986a, vout 44 + {script: []byte{ + btcscript.OP_1, btcscript.OP_DATA_65, + 0x34, 0x63, 0x33, 0x65, 0x63, 0x32, 0x35, 0x39, + 0x63, 0x37, 0x34, 0x64, 0x61, 0x63, 0x65, 0x36, + 0x66, 0x64, 0x30, 0x38, 0x38, 0x62, 0x34, 0x34, + 0x63, 0x65, 0x66, 0x38, 0x63, 0x0a, 0x63, 0x36, + 0x36, 0x62, 0x63, 0x31, 0x39, 0x39, 0x36, 0x63, + 0x38, 0x62, 0x39, 0x34, 0x61, 0x33, 0x38, 0x31, + 0x31, 0x62, 0x33, 0x36, 0x35, 0x36, 0x31, 0x38, + 0x66, 0x65, 0x31, 0x65, 0x39, 0x62, 0x31, 0x62, + 0x35, btcscript.OP_DATA_65, + 0x36, 0x63, 0x61, 0x63, 0x63, 0x65, 0x39, 0x39, + 0x33, 0x61, 0x33, 0x39, 0x38, 0x38, 0x61, 0x34, + 0x36, 0x39, 0x66, 0x63, 0x63, 0x36, 0x64, 0x36, + 0x64, 0x61, 0x62, 0x66, 0x64, 0x0a, 0x32, 0x36, + 0x36, 0x33, 0x63, 0x66, 0x61, 0x39, 0x63, 0x66, + 0x34, 0x63, 0x30, 0x33, 0x63, 0x36, 0x30, 0x39, + 0x63, 0x35, 0x39, 0x33, 0x63, 0x33, 0x65, 0x39, + 0x31, 0x66, 0x65, 0x64, 0x65, 0x37, 0x30, 0x32, + 0x39, btcscript.OP_DATA_33, + 0x31, 0x32, 0x33, 0x64, 0x64, 0x34, 0x32, 0x64, + 0x32, 0x35, 0x36, 0x33, 0x39, 0x64, 0x33, 0x38, + 0x61, 0x36, 0x63, 0x66, 0x35, 0x30, 0x61, 0x62, + 0x34, 0x63, 0x64, 0x34, 0x34, 0x0a, 0x00, 0x00, + 0x00, btcscript.OP_3, btcscript.OP_CHECK_MULTISIG}, + class: btcscript.ScriptMultiSig, + reqSigs: 1, + addrhashes: [][]byte{ + []byte{ + 0xfb, 0xf0, 0x08, 0x0b, 0xc5, 0xf9, 0xd7, 0x2a, + 0x9e, 0x64, 0x6f, 0x16, 0x46, 0x46, 0x1c, 0x43, + 0x19, 0xc3, 0xb6, 0xd4, + }, + []byte{ + 0xc6, 0x00, 0xe7, 0x69, 0xc3, 0xae, 0x20, 0xd4, + 0xa0, 0x50, 0x08, 0xd1, 0xe3, 0xad, 0x06, 0x33, + 0xf2, 0x7b, 0x77, 0xa2, + }, + []byte{ + 0xad, 0x34, 0x62, 0xcb, 0xa3, 0x5b, 0xee, 0x04, + 0xef, 0xd4, 0x20, 0x8c, 0xcd, 0x7f, 0x41, 0xf4, + 0xc8, 0x55, 0xf2, 0x73, + }, + }, + }, } func TestMultiSigs(t *testing.T) { From 3d60bac2386ce1d1cbf49bc4c737178b08434b45 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 3 Jan 2014 13:35:31 -0600 Subject: [PATCH 075/174] Add new funcs for creating payment scripts. This commit adds two new functions named PayToScriptHashScript and PayToAddrScript. The first one creates and returns a public-key script which pays to the provided script hash and conforms to BIP0016. The second function takes the new btcutil.Address interface type and returns an appropriate script to pay to the address type in the interface. It currently works for btcutil.AddressPubKeyHash and btcutil.AddressScriptHash. --- script.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/script.go b/script.go index 0e06e00d..3288ca11 100644 --- a/script.go +++ b/script.go @@ -12,6 +12,7 @@ import ( "errors" "fmt" "github.com/conformal/btcec" + "github.com/conformal/btcutil" "github.com/conformal/btcwire" "github.com/davecgh/go-spew/spew" "io" @@ -112,6 +113,10 @@ var StackErrInvalidIndex = errors.New("Invalid script index") // that peforms operations other that pushing data to the stack. var StackErrNonPushOnly = errors.New("SigScript is non pushonly") +// ErrUnsupportedAddress is returned when a concrete type that implements +// a btcutil.Address is not a supported type. +var ErrUnsupportedAddress = errors.New("unsupported address type") + // Bip16Activation is the timestamp where BIP0016 is valid to use in the // blockchain. To be used to determine if BIP0016 should be called for or not. // This timestamp corresponds to Sun Apr 1 00:00:00 UTC 2012. @@ -969,6 +974,45 @@ func PayToPubKeyHashScript(pubKeyHash []byte) (pkScript []byte, err error) { return unparseScript(pops) } +// PayToScriptHashScript creates a new script to pay a transaction output to a +// script hash. +func PayToScriptHashScript(scriptHash []byte) (pkScript []byte, err error) { + pops := []parsedOpcode{ + parsedOpcode{ + opcode: opcodemap[OP_HASH160], + }, + parsedOpcode{ + opcode: opcodemap[OP_DATA_20], + data: scriptHash, + }, + parsedOpcode{ + opcode: opcodemap[OP_EQUAL], + }, + } + return unparseScript(pops) +} + +// PayToAddrScript creates a new script to pay a transaction output to a the +// specified address. Currently the only supported address types are +// btcutil.AddressPubKeyHash and btcutil.AddressScriptHash. +func PayToAddrScript(addr btcutil.Address) ([]byte, error) { + switch addr := addr.(type) { + case *btcutil.AddressPubKeyHash: + if addr == nil { + return nil, ErrUnsupportedAddress + } + return PayToPubKeyHashScript(addr.ScriptAddress()) + + case *btcutil.AddressScriptHash: + if addr == nil { + return nil, ErrUnsupportedAddress + } + return PayToScriptHashScript(addr.ScriptAddress()) + } + + return nil, ErrUnsupportedAddress +} + // SignatureScript creates an input signature script for tx to spend // BTC sent from a previous output to the owner of privkey. tx must // include all transaction inputs and outputs, however txin scripts are From 814c920c96974bcdcf5af43d505d63e1fb237460 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 3 Jan 2014 13:42:22 -0600 Subject: [PATCH 076/174] Add tests for new payment script creation funcs. --- script_test.go | 91 ++++++++++++++++++++++++++++++ test_coverage.txt | 140 ++++++++++++++++++++++++---------------------- 2 files changed, 163 insertions(+), 68 deletions(-) diff --git a/script_test.go b/script_test.go index d5f45679..690c15f1 100644 --- a/script_test.go +++ b/script_test.go @@ -9,6 +9,7 @@ import ( "crypto/ecdsa" "github.com/conformal/btcec" "github.com/conformal/btcscript" + "github.com/conformal/btcutil" "github.com/conformal/btcwire" "math/big" "testing" @@ -2786,3 +2787,93 @@ func TestStringifyClass(t *testing.T) { } } } + +// bogusAddress implements the btcutil.Address interface so the tests can ensure +// unsupported address types are handled properly. +type bogusAddress struct{} + +// EncodeAddress simply returns an empty string. It exists to satsify the +// btcutil.Address interface. +func (b *bogusAddress) EncodeAddress() string { + return "" +} + +// ScriptAddress simply returns an empty byte slice. It exists to satsify the +// btcutil.Address interface. +func (b *bogusAddress) ScriptAddress() []byte { + return []byte{} +} + +func TestPayToAddrScript(t *testing.T) { + // 1MirQ9bwyQcGVJPwKUgapu5ouK2E2Ey4gX + p2pkhMain, err := btcutil.NewAddressPubKeyHash([]byte{ + 0xe3, 0x4c, 0xce, 0x70, 0xc8, 0x63, 0x73, 0x27, 0x3e, 0xfc, + 0xc5, 0x4c, 0xe7, 0xd2, 0xa4, 0x91, 0xbb, 0x4a, 0x0e, 0x84, + }, btcwire.MainNet) + if err != nil { + t.Errorf("Unable to create public key hash address: %v", err) + return + } + + // Taken from transaction: + // b0539a45de13b3e0403909b8bd1a555b8cbe45fd4e3f3fda76f3a5f52835c29d + p2shMain, _ := btcutil.NewAddressScriptHashFromHash([]byte{ + 0xe8, 0xc3, 0x00, 0xc8, 0x79, 0x86, 0xef, 0xa8, 0x4c, 0x37, + 0xc0, 0x51, 0x99, 0x29, 0x01, 0x9e, 0xf8, 0x6e, 0xb5, 0xb4, + }, btcwire.MainNet) + if err != nil { + t.Errorf("Unable to create script hash address: %v", err) + return + } + + tests := []struct { + in btcutil.Address + expected []byte + err error + }{ + // pay-to-pubkey-hash address on mainnet + { + p2pkhMain, + []byte{ + 0x76, 0xa9, 0x14, 0xe3, 0x4c, 0xce, 0x70, 0xc8, + 0x63, 0x73, 0x27, 0x3e, 0xfc, 0xc5, 0x4c, 0xe7, + 0xd2, 0xa4, 0x91, 0xbb, 0x4a, 0x0e, 0x84, 0x88, + 0xac, + }, + nil, + }, + // pay-to-script-hash address on mainnet + { + p2shMain, + []byte{ + 0xa9, 0x14, 0xe8, 0xc3, 0x00, 0xc8, 0x79, 0x86, + 0xef, 0xa8, 0x4c, 0x37, 0xc0, 0x51, 0x99, 0x29, + 0x01, 0x9e, 0xf8, 0x6e, 0xb5, 0xb4, 0x87, + }, + nil, + }, + + // Supported address types with nil pointers. + {(*btcutil.AddressPubKeyHash)(nil), []byte{}, btcscript.ErrUnsupportedAddress}, + {(*btcutil.AddressScriptHash)(nil), []byte{}, btcscript.ErrUnsupportedAddress}, + + // Unsupported address type. + {&bogusAddress{}, []byte{}, btcscript.ErrUnsupportedAddress}, + } + + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + pkScript, err := btcscript.PayToAddrScript(test.in) + if err != test.err { + t.Errorf("PayToAddrScript #%d unexpected error - "+ + "got %v, want %v", i, err, test.err) + continue + } + + if !bytes.Equal(pkScript, test.expected) { + t.Errorf("PayToAddrScript #%d got: %x\nwant: %x", + i, pkScript, test.expected) + continue + } + } +} diff --git a/test_coverage.txt b/test_coverage.txt index b57291c4..8ec4a9c4 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -1,25 +1,25 @@ -github.com/conformal/btcscript/address.go scriptToAddrHashTemplate 100.00% (45/45) +github.com/conformal/btcscript/address.go scriptToAddrHashTemplate 100.00% (44/44) github.com/conformal/btcscript/script.go Script.Step 100.00% (37/37) github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (30/30) github.com/conformal/btcscript/script.go CalcScriptInfo 100.00% (25/25) github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23) -github.com/conformal/btcscript/script.go sigDER 100.00% (22/22) github.com/conformal/btcscript/script.go NewScript 100.00% (21/21) github.com/conformal/btcscript/stack.go asInt 100.00% (21/21) -github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (15/15) +github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (16/16) github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (14/14) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) -github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) -github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) +github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) +github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) -github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) +github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) @@ -27,47 +27,47 @@ github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) -github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) +github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) -github.com/conformal/btcscript/script.go unparseScript 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) +github.com/conformal/btcscript/script.go PayToAddrScript 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) -github.com/conformal/btcscript/script.go typeOfScript 100.00% (7/7) github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) +github.com/conformal/btcscript/script.go unparseScript 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) +github.com/conformal/btcscript/script.go typeOfScript 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) -github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) +github.com/conformal/btcscript/script.go isNullData 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) @@ -78,78 +78,82 @@ github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) -github.com/conformal/btcscript/script.go isNullData 100.00% (4/4) github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) -github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) -github.com/conformal/btcscript/script.go ScriptClass.String 100.00% (3/3) -github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) -github.com/conformal/btcscript/script.go setStack 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) -github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) -github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/conformal/btcscript/address.go ScriptToAddrHash 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/conformal/btcscript/script.go setStack 100.00% (3/3) +github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) +github.com/conformal/btcscript/script.go ScriptClass.String 100.00% (3/3) +github.com/conformal/btcscript/script.go PayToScriptHashScript 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/conformal/btcscript/script.go PayToPubKeyHashScript 100.00% (2/2) -github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) -github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) -github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) -github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) -github.com/conformal/btcscript/log.go init 100.00% (1/1) -github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) +github.com/conformal/btcscript/address.go ScriptToAddrHash 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) +github.com/conformal/btcscript/script.go PayToPubKeyHashScript 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) +github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) github.com/conformal/btcscript/opcode.go init 100.00% (1/1) -github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) +github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) -github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) +github.com/conformal/btcscript/log.go init 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) +github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) +github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) +github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.28% (57/58) +github.com/conformal/btcscript/address.go ScriptToAddrHashes 90.91% (10/11) github.com/conformal/btcscript/opcode.go opcodeCheckSig 90.62% (29/32) github.com/conformal/btcscript/script.go expectedInputs 85.71% (6/7) github.com/conformal/btcscript/script.go calcScriptHash 82.05% (32/39) github.com/conformal/btcscript/script.go Script.CheckErrorCondition 78.57% (11/14) github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) -github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) +github.com/conformal/btcscript/script.go CalcPkScriptAddrHashes 0.00% (0/15) +github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/10) +github.com/conformal/btcscript/script.go CalcMultiSigStats 0.00% (0/8) github.com/conformal/btcscript/script.go IsPushOnlyScript 0.00% (0/4) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript --------------------------- 96.33% (998/1036) +github.com/conformal/btcscript/log.go UseLogger 0.00% (0/1) +github.com/conformal/btcscript --------------------------- 93.78% (995/1061) From eb4fc19b95258863af88859a4ba2934d5199ca76 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 3 Jan 2014 18:47:00 -0600 Subject: [PATCH 077/174] Modify DisasmString to return partial disassembly. Rather than returning an empty string from DisasmString if a script fails to parse, return the disassembly up to the point of the failure along with [error] appended. The error is still returned in case the caller wants more information about the script parse failure. --- script.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/script.go b/script.go index 3288ca11..e46be23a 100644 --- a/script.go +++ b/script.go @@ -693,20 +693,24 @@ func removeOpcodeByData(pkscript []parsedOpcode, data []byte) []parsedOpcode { } -// DisasmString formats a disassembled script for one line printing. +// DisasmString formats a disassembled script for one line printing. When the +// script fails to parse, the returned string will contain the disassembled +// script up to the point the failure occurred along with the string '[error]' +// appended. In addition, the reason the script failed to parse is returned +// if the caller wants more information about the failure. func DisasmString(buf []byte) (string, error) { disbuf := "" opcodes, err := parseScript(buf) - if err != nil { - return "", err - } for _, pop := range opcodes { disbuf += pop.print(true) + " " } if disbuf != "" { disbuf = disbuf[:len(disbuf)-1] } - return disbuf, nil + if err != nil { + disbuf += "[error]" + } + return disbuf, err } // calcScriptHash will, given the a script and hashtype for the current From b7135909025c740fb009eb01d8c2a467c2c1d9d0 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Sat, 4 Jan 2014 09:56:02 -0600 Subject: [PATCH 078/174] Group the StackErrX definitions. This improves the godoc display and provides a cleaner separation of the error definitions from other variables. --- script.go | 147 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 76 insertions(+), 71 deletions(-) diff --git a/script.go b/script.go index e46be23a..87b0867c 100644 --- a/script.go +++ b/script.go @@ -19,99 +19,104 @@ import ( "time" ) -// StackErrShortScript is returned if the script has an opcode that is too long -// for the length of the script. -var StackErrShortScript = errors.New("execute past end of script") +var ( + // StackErrShortScript is returned if the script has an opcode that is + // too long for the length of the script. + StackErrShortScript = errors.New("execute past end of script") -// StackErrUnderflow is returned if an opcode requires more items on the stack -// than is present. -var StackErrUnderflow = errors.New("stack underflow") + // StackErrUnderflow is returned if an opcode requires more items on the + // stack than is present. + StackErrUnderflow = errors.New("stack underflow") -// StackErrInvalidArgs is returned if the argument for an opcode is out of -// acceptable range. -var StackErrInvalidArgs = errors.New("invalid argument") + // StackErrInvalidArgs is returned if the argument for an opcode is out + // of acceptable range. + StackErrInvalidArgs = errors.New("invalid argument") -// StackErrOpDisabled is returned when a disabled opcode is encountered in the -// script. -var StackErrOpDisabled = errors.New("Disabled Opcode") + // StackErrOpDisabled is returned when a disabled opcode is encountered + // in the script. + StackErrOpDisabled = errors.New("Disabled Opcode") -// StackErrVerifyFailed is returned when one of the OP_VERIFY or OP_*VERIFY -// instructions is executed and the conditions fails. -var StackErrVerifyFailed = errors.New("Verify failed") + // StackErrVerifyFailed is returned when one of the OP_VERIFY or + // OP_*VERIFY instructions is executed and the conditions fails. + StackErrVerifyFailed = errors.New("Verify failed") -// StackErrNumberTooBig is returned when the argument for an opcode that should -// be an offset is obviously far too large. -var StackErrNumberTooBig = errors.New("number too big") + // StackErrNumberTooBig is returned when the argument for an opcode that + // should be an offset is obviously far too large. + StackErrNumberTooBig = errors.New("number too big") -// StackErrInvalidOpcode is returned when an opcode marked as invalid or a -// completely undefined opcode is encountered. -var StackErrInvalidOpcode = errors.New("Invalid Opcode") + // StackErrInvalidOpcode is returned when an opcode marked as invalid or + // a completely undefined opcode is encountered. + StackErrInvalidOpcode = errors.New("Invalid Opcode") -// StackErrReservedOpcode is returned when an opcode marked as reserved is -// encountered. -var StackErrReservedOpcode = errors.New("Reserved Opcode") + // StackErrReservedOpcode is returned when an opcode marked as reserved + // is encountered. + StackErrReservedOpcode = errors.New("Reserved Opcode") -// StackErrEarlyReturn is returned when OP_RETURN is executed in the script. -var StackErrEarlyReturn = errors.New("Script returned early") + // StackErrEarlyReturn is returned when OP_RETURN is executed in the + // script. + StackErrEarlyReturn = errors.New("Script returned early") -// StackErrNoIf is returned if an OP_ELSE or OP_ENDIF is encountered without -// first having an OP_IF or OP_NOTIF in the script. -var StackErrNoIf = errors.New("OP_ELSE or OP_ENDIF with no matching OP_IF") + // StackErrNoIf is returned if an OP_ELSE or OP_ENDIF is encountered + // without first having an OP_IF or OP_NOTIF in the script. + StackErrNoIf = errors.New("OP_ELSE or OP_ENDIF with no matching OP_IF") -// StackErrMissingEndif is returned if the end of a script is reached without -// and OP_ENDIF to correspond to a conditional expression. -var StackErrMissingEndif = fmt.Errorf("execute fail, in conditional execution") + // StackErrMissingEndif is returned if the end of a script is reached + // without and OP_ENDIF to correspond to a conditional expression. + StackErrMissingEndif = fmt.Errorf("execute fail, in conditional execution") -// StackErrTooManyPubkeys is returned if an OP_CHECKMULTISIG is encountered -// with more than MaxPubKeysPerMultiSig pubkeys present. -var StackErrTooManyPubkeys = errors.New("Invalid pubkey count in OP_CHECKMULTISIG") + // StackErrTooManyPubkeys is returned if an OP_CHECKMULTISIG is + // encountered with more than MaxPubKeysPerMultiSig pubkeys present. + StackErrTooManyPubkeys = errors.New("Invalid pubkey count in OP_CHECKMULTISIG") -// StackErrTooManyOperations is returned if a script has more then -// MaxOpsPerScript opcodes that do not push data. -var StackErrTooManyOperations = errors.New("Too many operations in script") + // StackErrTooManyOperations is returned if a script has more than + // MaxOpsPerScript opcodes that do not push data. + StackErrTooManyOperations = errors.New("Too many operations in script") -// StackErrElementTooBig is returned if the size of an element to be pushed to -// the stack is over MaxScriptElementSize. -var StackErrElementTooBig = errors.New("Element in script too large") + // StackErrElementTooBig is returned if the size of an element to be + // pushed to the stack is over MaxScriptElementSize. + StackErrElementTooBig = errors.New("Element in script too large") -// StackErrUnknownAddress is returned when ScriptToAddrHash does not recognise -// the pattern of the script and thus can not find the address for payment. -var StackErrUnknownAddress = errors.New("non-recognised address") + // StackErrUnknownAddress is returned when ScriptToAddrHash does not + // recognise the pattern of the script and thus can not find the address + // for payment. + StackErrUnknownAddress = errors.New("non-recognised address") -// StackErrScriptFailed is returned when at the end of a script the boolean -// on top of the stack is false signifying that the script has failed. -var StackErrScriptFailed = errors.New("execute fail, fail on stack") + // StackErrScriptFailed is returned when at the end of a script the + // boolean on top of the stack is false signifying that the script has + // failed. + StackErrScriptFailed = errors.New("execute fail, fail on stack") -// StackErrScriptUnfinished is returned when CheckErrorCondition is called -// on a script that has not finished executing. -var StackErrScriptUnfinished = errors.New("Error check when script unfinished") + // StackErrScriptUnfinished is returned when CheckErrorCondition is + // called on a script that has not finished executing. + StackErrScriptUnfinished = errors.New("Error check when script unfinished") -// StackErrEmpyStack is returned when the stack is empty at the end of -// execution. Normal operation requires that a boolean is on top of the stack -// when the scripts have finished executing. -var StackErrEmptyStack = errors.New("Stack empty at end of execution") + // StackErrEmpyStack is returned when the stack is empty at the end of + // execution. Normal operation requires that a boolean is on top of the + // stack when the scripts have finished executing. + StackErrEmptyStack = errors.New("Stack empty at end of execution") -// StackErrP2SHNonPushOnly is returned when a Pay-to-Script-Hash transaction -// is encountered and the ScriptSig does operations other than push data (in -// violation of bip16). -var StackErrP2SHNonPushOnly = errors.New("pay to script hash with non " + - "pushonly input") + // StackErrP2SHNonPushOnly is returned when a Pay-to-Script-Hash + // transaction is encountered and the ScriptSig does operations other + // than push data (in violation of bip16). + StackErrP2SHNonPushOnly = errors.New("pay to script hash with non " + + "pushonly input") -// StackErrInvalidParseType is an internal error returned from ScriptToAddrHash -// ony if the internal data tables are wrong. -var StackErrInvalidParseType = errors.New("internal error: invalid parsetype found") + // StackErrInvalidParseType is an internal error returned from + // ScriptToAddrHash ony if the internal data tables are wrong. + StackErrInvalidParseType = errors.New("internal error: invalid parsetype found") -// StackErrInvalidAddrOffset is an internal error returned from ScriptToAddrHash -// ony if the internal data tables are wrong. -var StackErrInvalidAddrOffset = errors.New("internal error: invalid offset found") + // StackErrInvalidAddrOffset is an internal error returned from + // ScriptToAddrHash ony if the internal data tables are wrong. + StackErrInvalidAddrOffset = errors.New("internal error: invalid offset found") -// StackErrInvalidIndex is returned when an out-of-bounds index was passed to -// a function. -var StackErrInvalidIndex = errors.New("Invalid script index") + // StackErrInvalidIndex is returned when an out-of-bounds index was + // passed to a function. + StackErrInvalidIndex = errors.New("Invalid script index") -// StackErrNonPushOnly is returned when ScriptInfo is called with a pkScript -// that peforms operations other that pushing data to the stack. -var StackErrNonPushOnly = errors.New("SigScript is non pushonly") + // StackErrNonPushOnly is returned when ScriptInfo is called with a + // pkScript that peforms operations other that pushing data to the stack. + StackErrNonPushOnly = errors.New("SigScript is non pushonly") +) // ErrUnsupportedAddress is returned when a concrete type that implements // a btcutil.Address is not a supported type. From 2005fae90834a88c31281ecf04cf697aba9d0d1e Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Sat, 4 Jan 2014 15:13:29 -0600 Subject: [PATCH 079/174] Change OP_CHECK_MULTISIG -> OP_CHECKMULTISIG. This change was made to match the reference implementation. --- address.go | 2 +- address_test.go | 10 ++++---- internal_test.go | 8 +++---- opcode.go | 4 ++-- opcode_test.go | 62 ++++++++++++++++++++++++------------------------ script.go | 6 ++--- script_test.go | 16 ++++++------- 7 files changed, 54 insertions(+), 54 deletions(-) diff --git a/address.go b/address.go index 5407ac12..667c98a7 100644 --- a/address.go +++ b/address.go @@ -128,7 +128,7 @@ func scriptToAddrHashTemplate(script []byte, validformats []pkformat) (ScriptTyp if success == false { if len(script) > 1 { // check for a few special case - if script[len(script)-1] == OP_CHECK_MULTISIG { + if script[len(script)-1] == OP_CHECKMULTISIG { return ScriptStrange, nil, nil } if script[0] == OP_0 && (len(script) <= 75 && byte(len(script)) == script[1]+2) { diff --git a/address_test.go b/address_test.go index 12b3be42..38d9c6cd 100644 --- a/address_test.go +++ b/address_test.go @@ -146,7 +146,7 @@ var addressTests = []addressTest{ 0xa7, 0xa8, 0x45, 0xbd, 0x25, 0x68, 0x9e, 0xdb, 0x72, 0x3d, 0x5a, 0xd4, 0x06, 0x8d, 0xdd, 0x30, 0x36, - btcscript.OP_CHECK_MULTISIG, // note this isn't a real tx + btcscript.OP_CHECKMULTISIG, // note this isn't a real tx }, addrhash: nil, class: btcscript.ScriptStrange, @@ -305,7 +305,7 @@ var multiSigTests = []multiSigTest{ 0x0e, 0x4e, 0xf8, 0x55, 0x19, 0x46, 0xd8, 0xa5, 0x40, 0x91, 0x1a, 0xbe, 0x3e, 0x78, 0x54, 0xa2, 0x6f, 0x39, 0xf5, 0x8b, 0x25, 0xc1, 0x53, 0x42, - 0xaf, btcscript.OP_2, btcscript.OP_CHECK_MULTISIG}, + 0xaf, btcscript.OP_2, btcscript.OP_CHECKMULTISIG}, class: btcscript.ScriptMultiSig, reqSigs: 1, addrhashes: [][]byte{ @@ -342,7 +342,7 @@ var multiSigTests = []multiSigTest{ 0x0e, 0x4e, 0xf8, 0x55, 0x19, 0x46, 0xd8, 0xa5, 0x40, 0x91, 0x1a, 0xbe, 0x3e, 0x78, 0x54, 0xa2, 0x6f, 0x39, 0xf5, 0x8b, 0x25, 0xc1, 0x53, 0x42, - 0xaf, btcscript.OP_2, btcscript.OP_CHECK_MULTISIG}, + 0xaf, btcscript.OP_2, btcscript.OP_CHECKMULTISIG}, class: btcscript.ScriptMultiSig, reqSigs: 1, addrhashes: [][]byte{ @@ -388,7 +388,7 @@ var multiSigTests = []multiSigTest{ 0x20, 0x36, 0x63, 0x35, 0x33, 0x63, 0x64, 0x39, 0x38, 0x37, 0x31, 0x31, 0x39, 0x65, 0x66, 0x37, 0x39, 0x37, 0x64, 0x35, 0x61, 0x64, 0x63, 0x63, - 0x64, btcscript.OP_3, btcscript.OP_CHECK_MULTISIG}, + 0x64, btcscript.OP_3, btcscript.OP_CHECKMULTISIG}, class: btcscript.ScriptMultiSig, reqSigs: 1, addrhashes: [][]byte{ @@ -435,7 +435,7 @@ var multiSigTests = []multiSigTest{ 0x32, 0x35, 0x36, 0x33, 0x39, 0x64, 0x33, 0x38, 0x61, 0x36, 0x63, 0x66, 0x35, 0x30, 0x61, 0x62, 0x34, 0x63, 0x64, 0x34, 0x34, 0x0a, 0x00, 0x00, - 0x00, btcscript.OP_3, btcscript.OP_CHECK_MULTISIG}, + 0x00, btcscript.OP_3, btcscript.OP_CHECKMULTISIG}, class: btcscript.ScriptMultiSig, reqSigs: 1, addrhashes: [][]byte{ diff --git a/internal_test.go b/internal_test.go index 9d75ce88..0d03b0f7 100644 --- a/internal_test.go +++ b/internal_test.go @@ -3544,17 +3544,17 @@ var popTests = []popTest{ expectedErr: StackErrInvalidOpcode, }, popTest{ - name: "OP_CHECK_MULTISIG", + name: "OP_CHECKMULTISIG", pop: &parsedOpcode{ - opcode: opcodemapPreinit[OP_CHECK_MULTISIG], + opcode: opcodemapPreinit[OP_CHECKMULTISIG], data: nil, }, expectedErr: nil, }, popTest{ - name: "OP_CHECK_MULTISIG long", + name: "OP_CHECKMULTISIG long", pop: &parsedOpcode{ - opcode: opcodemapPreinit[OP_CHECK_MULTISIG], + opcode: opcodemapPreinit[OP_CHECKMULTISIG], data: make([]byte, 1), }, expectedErr: StackErrInvalidOpcode, diff --git a/opcode.go b/opcode.go index d93f1f8d..241caaf6 100644 --- a/opcode.go +++ b/opcode.go @@ -211,7 +211,7 @@ const ( OP_CODESEPARATOR = 171 OP_CHECKSIG = 172 OP_CHECKSIGVERIFY = 173 - OP_CHECK_MULTISIG = 174 + OP_CHECKMULTISIG = 174 OP_CHECKMULTISIGVERIFY = 175 OP_NOP1 = 176 OP_NOP2 = 177 @@ -664,7 +664,7 @@ var opcodemapPreinit = map[byte]*opcode{ opfunc: opcodeCheckSig}, OP_CHECKSIGVERIFY: {value: OP_CHECKSIGVERIFY, name: "OP_CHECKSIGVERIFY", length: 1, opfunc: opcodeCheckSigVerify}, - OP_CHECK_MULTISIG: {value: OP_CHECK_MULTISIG, name: "OP_CHECK_MULTISIG", length: 1, + OP_CHECKMULTISIG: {value: OP_CHECKMULTISIG, name: "OP_CHECKMULTISIG", length: 1, opfunc: opcodeCheckMultiSig}, OP_CHECKMULTISIGVERIFY: {value: OP_CHECKMULTISIGVERIFY, name: "OP_CHECKMULTISIGVERIFY", length: 1, diff --git a/opcode_test.go b/opcode_test.go index 70349be3..6fa50a65 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -381,7 +381,7 @@ var opcodeTests = []opcodeTest{ 0xa7, 0xdf, 0x5f, 0x14, 0x2c, 0x21, 0xc1, 0xb7, 0x30, 0x3b, 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, - btcscript.OP_1, btcscript.OP_CHECK_MULTISIG}, + btcscript.OP_1, btcscript.OP_CHECKMULTISIG}, canonical: false, shouldPass: false}, {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_DATA_65, @@ -392,7 +392,7 @@ var opcodeTests = []opcodeTest{ 0xa7, 0xdf, 0x5f, 0x14, 0x2c, 0x21, 0xc1, 0xb7, 0x30, 0x3b, 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, - btcscript.OP_1, btcscript.OP_CHECK_MULTISIG}, + btcscript.OP_1, btcscript.OP_CHECKMULTISIG}, canonical: true, shouldPass: false}, /* up here because no defined error case. */ @@ -2162,44 +2162,44 @@ var detailedTests = []detailedTest{ nPreciseSigOps: 1, }, { - name: "OP_CHECK_MULTISIG no args", - script: []byte{btcscript.OP_CHECK_MULTISIG}, + name: "OP_CHECKMULTISIG no args", + script: []byte{btcscript.OP_CHECKMULTISIG}, expectedReturn: btcscript.StackErrUnderflow, - disassembly: "OP_CHECK_MULTISIG", + disassembly: "OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 20, }, { - name: "OP_CHECK_MULTISIG huge number", + name: "OP_CHECKMULTISIG huge number", script: []byte{btcscript.OP_PUSHDATA1, 0x9, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, - btcscript.OP_CHECK_MULTISIG}, + btcscript.OP_CHECKMULTISIG}, expectedReturn: btcscript.StackErrNumberTooBig, - disassembly: "010203040506070809 OP_CHECK_MULTISIG", + disassembly: "010203040506070809 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 20, }, { - name: "OP_CHECK_MULTISIG too many keys", + name: "OP_CHECKMULTISIG too many keys", script: []byte{btcscript.OP_DATA_1, 21, - btcscript.OP_CHECK_MULTISIG}, + btcscript.OP_CHECKMULTISIG}, expectedReturn: btcscript.StackErrTooManyPubkeys, - disassembly: "15 OP_CHECK_MULTISIG", + disassembly: "15 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 20, }, { - name: "OP_CHECK_MULTISIG lying about pubkeys", + name: "OP_CHECKMULTISIG lying about pubkeys", script: []byte{btcscript.OP_1, - btcscript.OP_CHECK_MULTISIG}, + btcscript.OP_CHECKMULTISIG}, expectedReturn: btcscript.StackErrUnderflow, - disassembly: "OP_1 OP_CHECK_MULTISIG", + disassembly: "OP_1 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 1, }, { // pubkey comes from blockchain - name: "OP_CHECK_MULTISIG no sigs", + name: "OP_CHECKMULTISIG no sigs", script: []byte{ btcscript.OP_DATA_65, 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, @@ -2211,15 +2211,15 @@ var detailedTests = []detailedTest{ 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, btcscript.OP_1, - btcscript.OP_CHECK_MULTISIG}, + btcscript.OP_CHECKMULTISIG}, expectedReturn: btcscript.StackErrUnderflow, - disassembly: "04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECK_MULTISIG", + disassembly: "04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 1, }, { // pubkey comes from blockchain - name: "OP_CHECK_MULTISIG sigs huge no", + name: "OP_CHECKMULTISIG sigs huge no", script: []byte{ btcscript.OP_PUSHDATA1, 0x9, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, @@ -2233,14 +2233,14 @@ var detailedTests = []detailedTest{ 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, btcscript.OP_1, - btcscript.OP_CHECK_MULTISIG}, + btcscript.OP_CHECKMULTISIG}, expectedReturn: btcscript.StackErrNumberTooBig, - disassembly: "010203040506070809 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECK_MULTISIG", + disassembly: "010203040506070809 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 1, }, { - name: "OP_CHECK_MULTISIG too few sigs", + name: "OP_CHECKMULTISIG too few sigs", script: []byte{btcscript.OP_1, btcscript.OP_DATA_65, 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, @@ -2252,15 +2252,15 @@ var detailedTests = []detailedTest{ 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, btcscript.OP_1, - btcscript.OP_CHECK_MULTISIG}, + btcscript.OP_CHECKMULTISIG}, expectedReturn: btcscript.StackErrUnderflow, - disassembly: "OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECK_MULTISIG", + disassembly: "OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 1, }, { // pubkey and sig comes from blockchain, are unrelated - name: "OP_CHECK_MULTISIG won't verify", + name: "OP_CHECKMULTISIG won't verify", script: []byte{btcscript.OP_1, btcscript.OP_DATA_71, 0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69, 0x32, @@ -2282,9 +2282,9 @@ var detailedTests = []detailedTest{ 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, btcscript.OP_1, - btcscript.OP_CHECK_MULTISIG}, + btcscript.OP_CHECKMULTISIG}, after: [][]byte{{0}}, - disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECK_MULTISIG", + disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 1, }, @@ -2292,7 +2292,7 @@ var detailedTests = []detailedTest{ // invalid pubkey means that it fails to validate, not an // error. There are pubkeys in the blockchain that don't // parse with any validity. - name: "OP_CHECK_MULTISIG sigs bad pubkey", + name: "OP_CHECKMULTISIG sigs bad pubkey", script: []byte{btcscript.OP_1, btcscript.OP_DATA_71, 0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69, 0x32, @@ -2305,9 +2305,9 @@ var detailedTests = []detailedTest{ 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09, 0x01, btcscript.OP_1, btcscript.OP_1, btcscript.OP_1, - btcscript.OP_CHECK_MULTISIG}, + btcscript.OP_CHECKMULTISIG}, after: [][]byte{{0}}, - disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 OP_1 OP_1 OP_CHECK_MULTISIG", + disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 OP_1 OP_1 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 1, }, @@ -3090,10 +3090,10 @@ var detailedTests = []detailedTest{ btcscript.OP_1, btcscript.OP_1, btcscript.OP_2, - btcscript.OP_CHECK_MULTISIG, + btcscript.OP_CHECKMULTISIG, }, expectedReturn: btcscript.StackErrTooManyOperations, - disassembly: "OP_1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_1 OP_1 OP_1 OP_1 OP_2 OP_CHECK_MULTISIG", + disassembly: "OP_1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_1 OP_1 OP_1 OP_1 OP_2 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 2, }, diff --git a/script.go b/script.go index 87b0867c..20f0ac30 100644 --- a/script.go +++ b/script.go @@ -237,7 +237,7 @@ func IsPayToScriptHash(script []byte) bool { func isMultiSig(pops []parsedOpcode) bool { l := len(pops) // absolute minimum is 1 pubkey so - // OP_1-16, pubkey, OP_1, OP_CHECK_MULTISIG + // OP_1-16, pubkey, OP_1, OP_CHECKMULTISIG if l < 4 { return false } @@ -249,7 +249,7 @@ func isMultiSig(pops []parsedOpcode) bool { pops[l-2].opcode.value > OP_16 { return false } - if pops[l-1].opcode.value != OP_CHECK_MULTISIG { + if pops[l-1].opcode.value != OP_CHECKMULTISIG { return false } for _, pop := range pops[1 : l-2] { @@ -936,7 +936,7 @@ func getSigOpCount(pops []parsedOpcode, precise bool) int { fallthrough case OP_CHECKSIGVERIFY: nSigs++ - case OP_CHECK_MULTISIG: + case OP_CHECKMULTISIG: fallthrough case OP_CHECKMULTISIGVERIFY: // If we are being precise then look for familiar diff --git a/script_test.go b/script_test.go index 690c15f1..c98bb188 100644 --- a/script_test.go +++ b/script_test.go @@ -958,7 +958,7 @@ var txTests = []txTest{ 0x78, 0x86, 0x21, 0x1a, 0xb4, 0x14, 0xd5, 0x5a, btcscript.OP_TRUE, - btcscript.OP_CHECK_MULTISIG, + btcscript.OP_CHECKMULTISIG, }, Sequence: 4294967295, }, @@ -1081,7 +1081,7 @@ var txTests = []txTest{ 0x78, 0x86, 0x21, 0x1a, 0xb4, 0x14, 0xd5, 0x5a, btcscript.OP_TRUE, - btcscript.OP_CHECK_MULTISIG, + btcscript.OP_CHECKMULTISIG, }, Sequence: 4294967295, }, @@ -1711,7 +1711,7 @@ func TestScriptInfo(t *testing.T) { 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, - btcscript.OP_3, btcscript.OP_CHECK_MULTISIG, + btcscript.OP_3, btcscript.OP_CHECKMULTISIG, }, bip16: true, scriptInfo: btcscript.ScriptInfo{ @@ -1990,7 +1990,7 @@ var scriptTypeTests = []scriptTypeTest{ 0x45, 0x32, 0x9a, 0x00, 0x35, 0x7b, 0x3a, 0x78, 0x86, 0x21, 0x1a, 0xb4, 0x14, 0xd5, 0x5a, btcscript.OP_TRUE, - btcscript.OP_CHECK_MULTISIG, + btcscript.OP_CHECKMULTISIG, }, scripttype: btcscript.MultiSigTy, }, @@ -2091,7 +2091,7 @@ var scriptTypeTests = []scriptTypeTest{ 0x45, 0x32, 0x9a, 0x00, 0x35, 0x7b, 0x3a, 0x78, 0x86, 0x21, 0x1a, 0xb4, 0x14, 0xd5, 0x5a, btcscript.OP_TRUE, - btcscript.OP_CHECK_MULTISIG, + btcscript.OP_CHECKMULTISIG, }, scripttype: btcscript.NonStandardTy, }, @@ -2102,7 +2102,7 @@ var scriptTypeTests = []scriptTypeTest{ btcscript.OP_TRUE, btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_CHECK_MULTISIG, + btcscript.OP_CHECKMULTISIG, }, scripttype: btcscript.NonStandardTy, }, @@ -2122,7 +2122,7 @@ var scriptTypeTests = []scriptTypeTest{ 0x45, 0x32, 0x9a, 0x00, 0x35, 0x7b, 0x3a, 0x78, 0x86, 0x21, 0x1a, 0xb4, 0x14, 0xd5, 0x5a, // No number. - btcscript.OP_CHECK_MULTISIG, + btcscript.OP_CHECKMULTISIG, }, scripttype: btcscript.NonStandardTy, }, @@ -2146,7 +2146,7 @@ var scriptTypeTests = []scriptTypeTest{ // multisig but wrong length. script: []byte{ btcscript.OP_TRUE, - btcscript.OP_CHECK_MULTISIG, + btcscript.OP_CHECKMULTISIG, }, scripttype: btcscript.NonStandardTy, }, From e2f14e2cfa7cba1e46f960415244ca7545b24f13 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Mon, 6 Jan 2014 12:14:43 -0600 Subject: [PATCH 080/174] Fix comment typo. --- script.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script.go b/script.go index 20f0ac30..8cf11391 100644 --- a/script.go +++ b/script.go @@ -1122,7 +1122,7 @@ type ScriptInfo struct { // CalcScriptInfo returns a structure providing data about the scriptpair that // are provided as arguments. It will error if the pair is in someway invalid -// such taht they can not be analysed, i.e. if they do not parse or the +// such that they can not be analysed, i.e. if they do not parse or the // pkScript is not a push-only script func CalcScriptInfo(sigscript, pkscript []byte, bip16 bool) (*ScriptInfo, error) { si := new(ScriptInfo) From 126991b60bc6ee1ef0196cd96e40f04058144229 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Mon, 6 Jan 2014 20:43:52 -0600 Subject: [PATCH 081/174] Make opcode disasm names match reference impl. This commit modifies the names of opcdoes shown in the oneline script disassembly to match the reference implementation. In particular OP_1NEGATE, and OP_0 through OP_16 are changed to the raw numbers they represent when doing oneline disassembly. When doing full disassembly, the full opcode names are still shown. ok @owainga. --- opcode.go | 39 ++++++++++- opcode_test.go | 172 +++++++++++++++++++++++----------------------- test_coverage.txt | 4 +- 3 files changed, 126 insertions(+), 89 deletions(-) diff --git a/opcode.go b/opcode.go index 241caaf6..c4baac02 100644 --- a/opcode.go +++ b/opcode.go @@ -831,6 +831,31 @@ var opcodemapPreinit = map[byte]*opcode{ opfunc: opcodeInvalid}, } +// opcodeOnelineRepls defines opcode names which are replaced when doing a +// one-line disassembly. This is done to match the output of the reference +// implementation while not changing the opcode names in the nicer full +// disassembly. +var opcodeOnelineRepls = map[string]string{ + "OP_1NEGATE": "-1", + "OP_0": "0", + "OP_1": "1", + "OP_2": "2", + "OP_3": "3", + "OP_4": "4", + "OP_5": "5", + "OP_6": "6", + "OP_7": "7", + "OP_8": "8", + "OP_9": "9", + "OP_10": "10", + "OP_11": "11", + "OP_12": "12", + "OP_13": "13", + "OP_14": "14", + "OP_15": "15", + "OP_16": "16", +} + type parsedOpcode struct { opcode *opcode data []byte @@ -868,7 +893,19 @@ func (pop *parsedOpcode) exec(s *Script) error { } func (pop *parsedOpcode) print(oneline bool) string { - retString := pop.opcode.name + // The reference implementation one-line disassembly replaces opcodes + // which represent values (e.g. OP_0 through OP_16 and OP_1NEGATE) + // with the raw value. However, when not doing a one-line dissassembly, + // we prefer to show the actual opcode names. Thus, only replace the + // opcodes in question when the oneline flag is set. + opcodeName := pop.opcode.name + if oneline { + if replName, ok := opcodeOnelineRepls[opcodeName]; ok { + opcodeName = replName + } + } + + retString := opcodeName if pop.opcode.length == 1 { return retString } diff --git a/opcode_test.go b/opcode_test.go index 6fa50a65..0c446b0f 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -998,14 +998,14 @@ var detailedTests = []detailedTest{ before: [][]byte{}, script: []byte{btcscript.OP_1NEGATE}, after: [][]byte{{0x81}}, - disassembly: "OP_1NEGATE", + disassembly: "-1", }, { name: "add one to minus one", before: [][]byte{}, script: []byte{btcscript.OP_1NEGATE, btcscript.OP_1ADD}, after: [][]byte{{}}, // 0 - disassembly: "OP_1NEGATE OP_1ADD", + disassembly: "-1 OP_1ADD", }, { name: "OP_ABS (positive)", @@ -2132,7 +2132,7 @@ var detailedTests = []detailedTest{ name: "OP_CHECKSIG one arg", script: []byte{btcscript.OP_1, btcscript.OP_CHECKSIG}, expectedReturn: btcscript.StackErrUnderflow, - disassembly: "OP_1 OP_CHECKSIG", + disassembly: "1 OP_CHECKSIG", nSigOps: 1, nPreciseSigOps: 1, }, @@ -2149,7 +2149,7 @@ var detailedTests = []detailedTest{ script: []byte{btcscript.OP_1, btcscript.OP_CHECKSIGVERIFY}, expectedReturn: btcscript.StackErrUnderflow, - disassembly: "OP_1 OP_CHECKSIGVERIFY", + disassembly: "1 OP_CHECKSIGVERIFY", nSigOps: 1, nPreciseSigOps: 1, }, @@ -2193,7 +2193,7 @@ var detailedTests = []detailedTest{ script: []byte{btcscript.OP_1, btcscript.OP_CHECKMULTISIG}, expectedReturn: btcscript.StackErrUnderflow, - disassembly: "OP_1 OP_CHECKMULTISIG", + disassembly: "1 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 1, }, @@ -2213,7 +2213,7 @@ var detailedTests = []detailedTest{ btcscript.OP_1, btcscript.OP_CHECKMULTISIG}, expectedReturn: btcscript.StackErrUnderflow, - disassembly: "04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIG", + disassembly: "04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c 1 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 1, }, @@ -2235,7 +2235,7 @@ var detailedTests = []detailedTest{ btcscript.OP_1, btcscript.OP_CHECKMULTISIG}, expectedReturn: btcscript.StackErrNumberTooBig, - disassembly: "010203040506070809 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIG", + disassembly: "010203040506070809 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c 1 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 1, }, @@ -2254,7 +2254,7 @@ var detailedTests = []detailedTest{ btcscript.OP_1, btcscript.OP_CHECKMULTISIG}, expectedReturn: btcscript.StackErrUnderflow, - disassembly: "OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIG", + disassembly: "1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c 1 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 1, }, @@ -2284,7 +2284,7 @@ var detailedTests = []detailedTest{ btcscript.OP_1, btcscript.OP_CHECKMULTISIG}, after: [][]byte{{0}}, - disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIG", + disassembly: "1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c 1 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 1, }, @@ -2307,7 +2307,7 @@ var detailedTests = []detailedTest{ btcscript.OP_1, btcscript.OP_1, btcscript.OP_CHECKMULTISIG}, after: [][]byte{{0}}, - disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 OP_1 OP_1 OP_CHECKMULTISIG", + disassembly: "1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 1 1 1 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 1, }, @@ -2345,7 +2345,7 @@ var detailedTests = []detailedTest{ script: []byte{btcscript.OP_1, btcscript.OP_CHECKMULTISIGVERIFY}, expectedReturn: btcscript.StackErrUnderflow, - disassembly: "OP_1 OP_CHECKMULTISIGVERIFY", + disassembly: "1 OP_CHECKMULTISIGVERIFY", nSigOps: 20, nPreciseSigOps: 1, }, @@ -2365,7 +2365,7 @@ var detailedTests = []detailedTest{ btcscript.OP_1, btcscript.OP_CHECKMULTISIGVERIFY}, expectedReturn: btcscript.StackErrUnderflow, - disassembly: "04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIGVERIFY", + disassembly: "04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c 1 OP_CHECKMULTISIGVERIFY", nSigOps: 20, nPreciseSigOps: 1, }, @@ -2386,7 +2386,7 @@ var detailedTests = []detailedTest{ btcscript.OP_1, btcscript.OP_CHECKMULTISIGVERIFY}, expectedReturn: btcscript.StackErrNumberTooBig, - disassembly: "010203040506070809 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIGVERIFY", + disassembly: "010203040506070809 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c 1 OP_CHECKMULTISIGVERIFY", nSigOps: 20, nPreciseSigOps: 1, }, @@ -2405,7 +2405,7 @@ var detailedTests = []detailedTest{ btcscript.OP_1, btcscript.OP_CHECKMULTISIGVERIFY}, expectedReturn: btcscript.StackErrUnderflow, - disassembly: "OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIGVERIFY", + disassembly: "1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c 1 OP_CHECKMULTISIGVERIFY", nSigOps: 20, nPreciseSigOps: 1, }, @@ -2435,7 +2435,7 @@ var detailedTests = []detailedTest{ btcscript.OP_1, btcscript.OP_CHECKMULTISIGVERIFY}, expectedReturn: btcscript.StackErrVerifyFailed, - disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIGVERIFY", + disassembly: "1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c 1 OP_CHECKMULTISIGVERIFY", nSigOps: 20, nPreciseSigOps: 1, }, @@ -2458,7 +2458,7 @@ var detailedTests = []detailedTest{ btcscript.OP_1, btcscript.OP_1, btcscript.OP_CHECKMULTISIGVERIFY}, expectedReturn: btcscript.StackErrVerifyFailed, - disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 OP_1 OP_1 OP_CHECKMULTISIGVERIFY", + disassembly: "1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 1 1 1 OP_CHECKMULTISIGVERIFY", nSigOps: 20, nPreciseSigOps: 1, }, @@ -2669,7 +2669,7 @@ var detailedTests = []detailedTest{ btcscript.OP_DUP, }, after: [][]byte{{1}, {1}}, - disassembly: "OP_1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP", + disassembly: "1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP", }, { // 202 operations + one push @@ -2879,7 +2879,7 @@ var detailedTests = []detailedTest{ btcscript.OP_DROP, }, expectedReturn: btcscript.StackErrTooManyOperations, - disassembly: "OP_1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP", + disassembly: "1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP", }, { // 202 operations + one push @@ -3093,7 +3093,7 @@ var detailedTests = []detailedTest{ btcscript.OP_CHECKMULTISIG, }, expectedReturn: btcscript.StackErrTooManyOperations, - disassembly: "OP_1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_1 OP_1 OP_1 OP_1 OP_2 OP_CHECKMULTISIG", + disassembly: "1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP 1 1 1 1 2 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 2, }, @@ -3828,403 +3828,403 @@ var detailedTests = []detailedTest{ name: "invalid opcode 186 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN186, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN186 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN186 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 187 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN187, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN187 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN187 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 188 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN188, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN188 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN188 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 189 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN189, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN189 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN189 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 190 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN190, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN190 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN190 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 191 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN191, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN191 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN191 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 192 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN192, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN192 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN192 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 193 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN193, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN193 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN193 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 194 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN194, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN194 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN194 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 195 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN195, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN195 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN195 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 196 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN196, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN196 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN196 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 197 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN197, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN197 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN197 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 198 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN198, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN198 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN198 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 199 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN199, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN199 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN199 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 200 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN200, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN200 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN200 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 201 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN201, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN201 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN201 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 202 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN202, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN202 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN202 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 203 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN203, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN203 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN203 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 204 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN204, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN204 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN204 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 205 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN205, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN205 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN205 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 206 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN206, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN206 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN206 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 207 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN207, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN207 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN207 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 208 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN208, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN208 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN208 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 209 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN209, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN209 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN209 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 210 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN210, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN210 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN210 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 211 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN211, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN211 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN211 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 212 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN212, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN212 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN212 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 213 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN213, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN213 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN213 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 214 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN214, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN214 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN214 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 215 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN215, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN215 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN215 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 216 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN216, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN216 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN216 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 217 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN217, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN217 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN217 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 218 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN218, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN218 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN218 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 219 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN219, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN219 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN219 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 220 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN220, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN220 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN220 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 221 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN221, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN221 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN221 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 222 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN222, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN222 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN222 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 223 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN223, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN223 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN223 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 224 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN224, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN224 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN224 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 225 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN225, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN225 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN225 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 226 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN226, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN226 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN226 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 227 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN227, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN227 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN227 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 228 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN228, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN228 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN228 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 229 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN229, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN229 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN229 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 230 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN230, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN230 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN230 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 231 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN231, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN231 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN231 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 232 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN232, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN232 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN232 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 233 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN233, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN233 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN233 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 234 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN234, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN234 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN234 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 235 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN235, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN235 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN235 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 236 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN236, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN236 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN236 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 237 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN237, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN237 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN237 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 238 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN238, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN238 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN238 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 239 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN239, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN239 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN239 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 240 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN240, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN240 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN240 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 241 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN241, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN241 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN241 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 242 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN242, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN242 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN242 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 243 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN243, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN243 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN243 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 244 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN244, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN244 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN244 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 245 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN245, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN245 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN245 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 246 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN246, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN246 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN246 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 247 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN247, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN247 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN247 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 248 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN248, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN248 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN248 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 249 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN249, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN249 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN249 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 250 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN250, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN250 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN250 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 251 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN251, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN251 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN251 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 252 if noexec", script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN252, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, after: [][]byte{{0x01}}, - disassembly: "OP_0 OP_IF OP_UNKNOWN252 OP_ELSE OP_1 OP_ENDIF", + disassembly: "0 OP_IF OP_UNKNOWN252 OP_ELSE 1 OP_ENDIF", }, { diff --git a/test_coverage.txt b/test_coverage.txt index 8ec4a9c4..4478ce22 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -6,13 +6,13 @@ github.com/conformal/btcscript/script.go CalcScriptInfo 100.00% (25/25) github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23) github.com/conformal/btcscript/script.go NewScript 100.00% (21/21) github.com/conformal/btcscript/stack.go asInt 100.00% (21/21) +github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (16/16) github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (16/16) github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (14/14) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) -github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) @@ -155,5 +155,5 @@ github.com/conformal/btcscript/script.go CalcMultiSigStats 0.00% (0/8) github.com/conformal/btcscript/script.go IsPushOnlyScript 0.00% (0/4) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) github.com/conformal/btcscript/log.go UseLogger 0.00% (0/1) -github.com/conformal/btcscript --------------------------- 93.78% (995/1061) +github.com/conformal/btcscript --------------------------- 93.80% (999/1065) From 6c8003b064af105a468ca08a4c2f94c3d66915fc Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Mon, 6 Jan 2014 20:49:01 -0600 Subject: [PATCH 082/174] Refactor and improve address extraction code. This commit significantly changes the address extraction code. The original code was written before some of the other newer code was written and as a result essentially duplicated some of the logic for handling standard scripts which is used elsewhere in the package. The following is a summary of what has changed: - CalcPkScriptAddrHashes, ScriptToAddrHash, and ScriptToAddrHashes have been replaced by ExtractPkScriptAddresses - The ScriptType type has been removed in favor of the existing ScriptClass type - The new function returns a slice of btcutil.Addresses instead of raw hashes that the caller then needs to figure out what to do with to convert them to proper addressses - The new function makes use of the existing ScriptClass instead of an nearly duplicate ScriptType - The new function hooks into the existing infrastructure for parsing scripts and identifying scripts of standard forms - The new function only works with pkscripts to match the behavior of the reference implementation - do note that the redeeming script from a p2sh script is still considered a pkscript - The logic combines extraction for all script types instead of using a separate function for multi-signature transactions - The new function ignores addresses which are invalid for some reason such as invalid public keys --- address.go | 260 ++++++++----------------- address_test.go | 490 ----------------------------------------------- internal_test.go | 63 ------ script.go | 32 ---- 4 files changed, 75 insertions(+), 770 deletions(-) delete mode 100644 address_test.go diff --git a/address.go b/address.go index 667c98a7..caeb680a 100644 --- a/address.go +++ b/address.go @@ -4,197 +4,87 @@ package btcscript -// ScriptType is an enum type that represents the type of a script. It is -// returned from ScriptToAddrHash as part of the metadata about the script. -// It implements the Stringer interface for nice printing. -type ScriptType int - -// String Converts the enumeration to a nice string value instead of a number. -func (t ScriptType) String() string { - if int(t) > len(scriptTypeToName) || int(t) < 0 { - return "Invalid" - } - return scriptTypeToName[t] -} - -// Constant types representing known types of script found in the wild -const ( - ScriptUnknown ScriptType = iota - ScriptAddr - ScriptPubKey - ScriptPayToScriptHash - ScriptMultiSig - ScriptStrange - ScriptGeneration +import ( + "github.com/conformal/btcutil" + "github.com/conformal/btcwire" ) -var scriptTypeToName = []string{ - ScriptUnknown: "Unknown", - ScriptAddr: "Addr", - ScriptPubKey: "Pubkey", - ScriptPayToScriptHash: "PayToScriptHash", - ScriptMultiSig: "MultiSig", - ScriptStrange: "Strange", - ScriptGeneration: "Generation", // ScriptToAddrHash does not recieve enough information to identify Generation scripts. -} +// ExtractPkScriptAddrs returns the type of script, addresses and required +// signatures associated with the passed PkScript. Note that it only works for +// 'standard' transaction script types. Any data such as public keys which are +// invalid are omitted from the results. +func ExtractPkScriptAddrs(pkScript []byte, net btcwire.BitcoinNet) (ScriptClass, []btcutil.Address, int, error) { + var addrs []btcutil.Address + var requiredSigs int -type pkformat struct { - addrtype ScriptType - parsetype int - length int - databytes []pkbytes - allowmore bool -} - -type pkbytes struct { - off int - val byte -} - -const ( - scrPayAddr = iota - scrCollectAddr - scrCollectAddrComp - scrGeneratePubkeyAddr - scrPubkeyAddr - scrPubkeyAddrComp - scrPayToScriptHash - scrNoAddr -) - -// ScriptToAddrHash extracts a 20-byte public key hash and the type out of a PkScript -func ScriptToAddrHash(script []byte) (ScriptType, []byte, error) { - // Currently this only understands one form of PkScript - validformats := []pkformat{ - {ScriptAddr, scrPayAddr, 25, []pkbytes{{0, OP_DUP}, {1, OP_HASH160}, {2, OP_DATA_20}, {23, OP_EQUALVERIFY}, {24, OP_CHECKSIG}}, true}, - {ScriptAddr, scrCollectAddr, 142, []pkbytes{{0, OP_DATA_75}, {76, OP_DATA_65}}, false}, - {ScriptAddr, scrCollectAddr, 141, []pkbytes{{0, OP_DATA_74}, {75, OP_DATA_65}}, false}, - {ScriptAddr, scrCollectAddr, 140, []pkbytes{{0, OP_DATA_73}, {74, OP_DATA_65}}, false}, - {ScriptAddr, scrCollectAddr, 139, []pkbytes{{0, OP_DATA_72}, {73, OP_DATA_65}}, false}, - {ScriptAddr, scrCollectAddr, 138, []pkbytes{{0, OP_DATA_71}, {72, OP_DATA_65}}, false}, - {ScriptAddr, scrCollectAddr, 137, []pkbytes{{0, OP_DATA_70}, {71, OP_DATA_65}}, false}, - {ScriptAddr, scrCollectAddr, 136, []pkbytes{{0, OP_DATA_69}, {70, OP_DATA_65}}, false}, - {ScriptAddr, scrCollectAddrComp, 110, []pkbytes{{0, OP_DATA_75}, {76, OP_DATA_33}}, false}, - {ScriptAddr, scrCollectAddrComp, 109, []pkbytes{{0, OP_DATA_74}, {75, OP_DATA_33}}, false}, - {ScriptAddr, scrCollectAddrComp, 108, []pkbytes{{0, OP_DATA_73}, {74, OP_DATA_33}}, false}, - {ScriptAddr, scrCollectAddrComp, 107, []pkbytes{{0, OP_DATA_72}, {73, OP_DATA_33}}, false}, - {ScriptAddr, scrCollectAddrComp, 106, []pkbytes{{0, OP_DATA_71}, {72, OP_DATA_33}}, false}, - {ScriptAddr, scrCollectAddrComp, 105, []pkbytes{{0, OP_DATA_70}, {71, OP_DATA_33}}, false}, - {ScriptAddr, scrCollectAddrComp, 104, []pkbytes{{0, OP_DATA_69}, {70, OP_DATA_33}}, false}, - {ScriptPubKey, scrGeneratePubkeyAddr, 74, []pkbytes{{0, OP_DATA_73}}, false}, - {ScriptPubKey, scrGeneratePubkeyAddr, 73, []pkbytes{{0, OP_DATA_72}}, false}, - {ScriptPubKey, scrGeneratePubkeyAddr, 72, []pkbytes{{0, OP_DATA_71}}, false}, - {ScriptPubKey, scrGeneratePubkeyAddr, 71, []pkbytes{{0, OP_DATA_70}}, false}, - {ScriptPubKey, scrGeneratePubkeyAddr, 70, []pkbytes{{0, OP_DATA_69}}, false}, - {ScriptPubKey, scrPubkeyAddr, 67, []pkbytes{{0, OP_DATA_65}, {66, OP_CHECKSIG}}, true}, - {ScriptPubKey, scrPubkeyAddrComp, 35, []pkbytes{{0, OP_DATA_33}, {34, OP_CHECKSIG}}, true}, - {ScriptPayToScriptHash, scrPayToScriptHash, 23, []pkbytes{{0, OP_HASH160}, {1, OP_DATA_20}, {22, OP_EQUAL}}, false}, - {ScriptStrange, scrNoAddr, 33, []pkbytes{{0, OP_DATA_32}}, false}, - } - return scriptToAddrHashTemplate(script, validformats) -} - -func scriptToAddrHashTemplate(script []byte, validformats []pkformat) (ScriptType, []byte, error) { - var format pkformat - var success bool - for _, format = range validformats { - if format.length != len(script) { - if len(script) < format.length { - continue - } - if !format.allowmore { - continue - } - } - success = true - for _, pkbyte := range format.databytes { - if pkbyte.off >= len(script) { - return ScriptUnknown, nil, - StackErrInvalidAddrOffset - } - if script[pkbyte.off] != pkbyte.val { - log.Tracef("off at byte %v %v %v", pkbyte.off, script[pkbyte.off], pkbyte.val) - success = false - break - } else { - log.Tracef("match at byte %v: ok", pkbyte.off) - } - } - if success == true { - break - } - } - - if success == false { - if len(script) > 1 { - // check for a few special case - if script[len(script)-1] == OP_CHECKMULTISIG { - return ScriptStrange, nil, nil - } - if script[0] == OP_0 && (len(script) <= 75 && byte(len(script)) == script[1]+2) { - return ScriptStrange, nil, nil - } - if script[0] == OP_DATA_36 && len(script) == 37 { - // Multisig ScriptSig - return ScriptStrange, nil, nil - } - } - - return ScriptUnknown, nil, StackErrUnknownAddress - } - - var addrhash []byte - switch format.parsetype { - case scrPayAddr: - addrhash = script[3:23] - case scrCollectAddr: - // script is replaced with the md160 of the pubkey - slen := len(script) - pubkey := script[slen-65:] - addrhash = calcHash160(pubkey) - case scrCollectAddrComp: - // script is replaced with the md160 of the pubkey - slen := len(script) - pubkey := script[slen-33:] - addrhash = calcHash160(pubkey) - case scrGeneratePubkeyAddr: - // unable to determine address hash from script - case scrNoAddr: - // unable to determine address hash from script - case scrPubkeyAddr: - pubkey := script[1:66] - addrhash = calcHash160(pubkey) - case scrPubkeyAddrComp: - pubkey := script[1:34] - addrhash = calcHash160(pubkey) - case scrPayToScriptHash: - addrhash = script[2:22] - default: - return ScriptUnknown, nil, StackErrInvalidParseType - } - - return format.addrtype, addrhash, nil -} - -// ScriptToAddrHashes extracts multiple 20-byte public key hashes -// from a MultiSig script. -func ScriptToAddrHashes(script []byte) (ScriptType, int, [][]byte, error) { - pops, err := parseScript(script) + // No valid addresses or required signatures if the script doesn't + // parse. + pops, err := parseScript(pkScript) if err != nil { - return ScriptUnknown, 0, nil, StackErrUnknownAddress + return NonStandardTy, nil, 0, err } - if !isMultiSig(pops) { - return ScriptUnknown, 0, nil, StackErrUnknownAddress + scriptClass := typeOfScript(pops) + switch scriptClass { + case PubKeyHashTy: + // A pay-to-pubkey-hash script is of the form: + // OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG + // Therefore the pubkey hash is the 3rd item on the stack. + // Skip the pubkey hash if it's invalid for some reason. + requiredSigs = 1 + addr, err := btcutil.NewAddressPubKeyHash(pops[2].data, net) + if err == nil { + addrs = append(addrs, addr) + } + + case PubKeyTy: + // A pay-to-pubkey script is of the form: + // OP_CHECKSIG + // Therefore the pubkey is the item on the stack. + // Skip the pubkey if it's invalid for some reason. + requiredSigs = 1 + addr, err := btcutil.NewAddressPubKey(pops[0].data, net) + if err == nil { + addrs = append(addrs, addr) + } + + case ScriptHashTy: + // A pay-to-script-hash script is of the form: + // OP_HASH160 OP_EQUAL + // Therefore the script hash is the 2nd item on the stack. + // Skip the script hash if it's invalid for some reason. + requiredSigs = 1 + addr, err := btcutil.NewAddressScriptHashFromHash(pops[1].data, net) + if err == nil { + addrs = append(addrs, addr) + } + + case MultiSigTy: + // A multi-signature script is of the form: + // ... OP_CHECKMULTISIG + // Therefore the number of required signatures is the 1st item + // on the stack and the number of public keys is the 2nd to last + // item on the stack. + requiredSigs = int(pops[0].opcode.value - (OP_1 - 1)) + numPubKeys := int(pops[len(pops)-2].opcode.value - (OP_1 - 1)) + + // Extract the public keys while skipping any that are invalid. + addrs = make([]btcutil.Address, 0, numPubKeys) + for i := 0; i < numPubKeys; i++ { + addr, err := btcutil.NewAddressPubKey(pops[i+1].data, net) + if err == nil { + addrs = append(addrs, addr) + } + } + + case NullDataTy: + // Null data transactions have no addresses or required + // signatures. + + case NonStandardTy: + // Don't attempt to extract addresses or required signatures for + // nonstandard transactions. } - l := len(pops) - addrHashes := make([][]byte, l-3) - for i, pop := range pops[1 : l-2] { - addrHashes[i] = calcHash160(pop.data) - } - - reqSigs := int(pops[0].opcode.value - (OP_1 - 1)) - - return ScriptMultiSig, reqSigs, addrHashes, nil + return scriptClass, addrs, requiredSigs, nil } diff --git a/address_test.go b/address_test.go deleted file mode 100644 index 38d9c6cd..00000000 --- a/address_test.go +++ /dev/null @@ -1,490 +0,0 @@ -// Copyright (c) 2013 Conformal Systems LLC. -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. -package btcscript_test - -import ( - "bytes" - "github.com/conformal/btcscript" - "testing" -) - -type addressTest struct { - script []byte - addrhash []byte - shouldFail error - class btcscript.ScriptType -} - -var addressTests = []addressTest{ - {script: []byte{btcscript.OP_DATA_65, - 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, - 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, - 0x1e, 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, - 0x2e, 0xca, 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, - 0x5c, 0xb2, 0xe0, 0xea, 0xdd, 0xfb, 0x84, 0xcc, - 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, - 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, - 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, - 0xa3, btcscript.OP_CHECKSIG}, - addrhash: []byte{0x11, 0xb3, 0x66, 0xed, 0xfc, 0x0a, - 0x8b, 0x66, 0xfe, 0xeb, 0xae, 0x5c, 0x2e, - 0x25, 0xa7, 0xb6, 0xa5, 0xd1, 0xcf, 0x31}, - class: btcscript.ScriptPubKey, - }, - {script: []byte{btcscript.OP_DATA_65, - 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, - 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, - 0x1e, 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, - 0x2e, 0xca, 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, - 0x5c, 0xb2, 0xe0, 0xea, 0xdd, 0xfb, 0x84, 0xcc, - 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, - 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, - 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, - 0xa3}, - shouldFail: btcscript.StackErrUnknownAddress, - }, - {script: []byte{btcscript.OP_DATA_71, - 0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69, - 0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, - 0xa1, 0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, - 0xe9, 0xd6, 0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, - 0x5f, 0xb8, 0xcd, 0x41, 0x02, 0x20, 0x18, 0x15, - 0x22, 0xec, 0x8e, 0xca, 0x07, 0xde, 0x48, 0x60, - 0xa4, 0xac, 0xdd, 0x12, 0x90, 0x9d, 0x83, 0x1c, - 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22, 0x08, 0x22, - 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09, 0x01}, - addrhash: nil, - class: btcscript.ScriptPubKey, - }, - {script: []byte{btcscript.OP_DUP, btcscript.OP_HASH160, - btcscript.OP_DATA_20, - 0xad, 0x06, 0xdd, 0x6d, 0xde, 0xe5, 0x5c, 0xbc, - 0xa9, 0xa9, 0xe3, 0x71, 0x3b, 0xd7, 0x58, 0x75, - 0x09, 0xa3, 0x05, 0x64, - btcscript.OP_EQUALVERIFY, btcscript.OP_CHECKSIG, - }, - addrhash: []byte{0xad, 0x06, 0xdd, 0x6d, 0xde, 0xe5, - 0x5c, 0xbc, 0xa9, 0xa9, 0xe3, 0x71, 0x3b, - 0xd7, 0x58, 0x75, 0x09, 0xa3, 0x05, 0x64}, - class: btcscript.ScriptAddr, - }, - {script: []byte{btcscript.OP_DATA_73, - 0x30, 0x46, 0x02, 0x21, 0x00, 0xdd, 0xc6, 0x97, - 0x38, 0xbf, 0x23, 0x36, 0x31, 0x8e, 0x4e, 0x04, - 0x1a, 0x5a, 0x77, 0xf3, 0x05, 0xda, 0x87, 0x42, - 0x8a, 0xb1, 0x60, 0x6f, 0x02, 0x32, 0x60, 0x01, - 0x78, 0x54, 0x35, 0x0d, 0xdc, 0x02, 0x21, 0x00, - 0x81, 0x7a, 0xf0, 0x9d, 0x2e, 0xec, 0x36, 0x86, - 0x2d, 0x16, 0x00, 0x98, 0x52, 0xb7, 0xe3, 0xa0, - 0xf6, 0xdd, 0x76, 0x59, 0x82, 0x90, 0xb7, 0x83, - 0x4e, 0x14, 0x53, 0x66, 0x03, 0x67, 0xe0, 0x7a, - 0x01, - btcscript.OP_DATA_65, - 0x04, 0xcd, 0x42, 0x40, 0xc1, 0x98, 0xe1, 0x25, - 0x23, 0xb6, 0xf9, 0xcb, 0x9f, 0x5b, 0xed, 0x06, - 0xde, 0x1b, 0xa3, 0x7e, 0x96, 0xa1, 0xbb, 0xd1, - 0x37, 0x45, 0xfc, 0xf9, 0xd1, 0x1c, 0x25, 0xb1, - 0xdf, 0xf9, 0xa5, 0x19, 0x67, 0x5d, 0x19, 0x88, - 0x04, 0xba, 0x99, 0x62, 0xd3, 0xec, 0xa2, 0xd5, - 0x93, 0x7d, 0x58, 0xe5, 0xa7, 0x5a, 0x71, 0x04, - 0x2d, 0x40, 0x38, 0x8a, 0x4d, 0x30, 0x7f, 0x88, - 0x7d}, - addrhash: []byte{0x40, 0x92, 0x08, 0xf3, 0x87, 0xf4, - 0x7f, 0xd2, 0x3a, 0x9f, 0x44, 0x5e, 0x14, - 0xdc, 0x1f, 0x99, 0xbb, 0xb8, 0x0d, 0xaa}, - class: btcscript.ScriptAddr, - }, - {script: []byte{btcscript.OP_DATA_73, - 0x30, 0x46, 0x02, 0x21, 0x00, 0xac, 0x7e, 0x4e, - 0x27, 0xf2, 0xb1, 0x1c, 0xb8, 0x6f, 0xb5, 0xaa, - 0x87, 0x2a, 0xb9, 0xd3, 0x2c, 0xdc, 0x08, 0x33, - 0x80, 0x73, 0x3e, 0x3e, 0x98, 0x47, 0xff, 0x77, - 0xa0, 0x69, 0xcd, 0xdf, 0xab, 0x02, 0x21, 0x00, - 0xc0, 0x4c, 0x3e, 0x6f, 0xfe, 0x88, 0xa1, 0x5b, - 0xc5, 0x07, 0xb8, 0xe5, 0x71, 0xaa, 0x35, 0x92, - 0x8a, 0xcf, 0xe1, 0x5a, 0x4a, 0x23, 0x20, 0x1b, - 0x08, 0xfe, 0x3c, 0x7b, 0x3c, 0x97, 0xc8, 0x8f, - 0x01, - btcscript.OP_DATA_33, - 0x02, 0x40, 0x05, 0xc9, 0x45, 0xd8, 0x6a, 0xc6, - 0xb0, 0x1f, 0xb0, 0x42, 0x58, 0x34, 0x5a, 0xbe, - 0xa7, 0xa8, 0x45, 0xbd, 0x25, 0x68, 0x9e, 0xdb, - 0x72, 0x3d, 0x5a, 0xd4, 0x06, 0x8d, 0xdd, 0x30, - 0x36, - }, - addrhash: []byte{0x0c, 0x1b, 0x83, 0xd0, 0x1d, 0x0f, - 0xfb, 0x2b, 0xcc, 0xae, 0x60, 0x69, 0x63, - 0x37, 0x6c, 0xca, 0x38, 0x63, 0xa7, 0xce}, - class: btcscript.ScriptAddr, - }, - {script: []byte{btcscript.OP_DATA_32, - 0x30, 0x46, 0x02, 0x21, 0x00, 0xac, 0x7e, 0x4e, - 0x27, 0xf2, 0xb1, 0x1c, 0xb8, 0x6f, 0xb5, 0xaa, - 0x87, 0x2a, 0xb9, 0xd3, 0x2c, 0xdc, 0x08, 0x33, - 0x80, 0x73, 0x3e, 0x3e, 0x98, 0x47, 0xff, 0x77, - }, - addrhash: nil, - class: btcscript.ScriptStrange, - }, - {script: []byte{btcscript.OP_DATA_33, - 0x02, 0x40, 0x05, 0xc9, 0x45, 0xd8, 0x6a, 0xc6, - 0xb0, 0x1f, 0xb0, 0x42, 0x58, 0x34, 0x5a, 0xbe, - 0xa7, 0xa8, 0x45, 0xbd, 0x25, 0x68, 0x9e, 0xdb, - 0x72, 0x3d, 0x5a, 0xd4, 0x06, 0x8d, 0xdd, 0x30, - 0x36, - btcscript.OP_CHECKSIG, - }, - addrhash: []byte{0x0c, 0x1b, 0x83, 0xd0, 0x1d, 0x0f, - 0xfb, 0x2b, 0xcc, 0xae, 0x60, 0x69, 0x63, - 0x37, 0x6c, 0xca, 0x38, 0x63, 0xa7, 0xce}, - class: btcscript.ScriptPubKey, - }, - {script: []byte{btcscript.OP_DATA_33, - 0x02, 0x40, 0x05, 0xc9, 0x45, 0xd8, 0x6a, 0xc6, - 0xb0, 0x1f, 0xb0, 0x42, 0x58, 0x34, 0x5a, 0xbe, - 0xa7, 0xa8, 0x45, 0xbd, 0x25, 0x68, 0x9e, 0xdb, - 0x72, 0x3d, 0x5a, 0xd4, 0x06, 0x8d, 0xdd, 0x30, - 0x36, - btcscript.OP_CHECKMULTISIG, // note this isn't a real tx - }, - addrhash: nil, - class: btcscript.ScriptStrange, - }, - {script: []byte{btcscript.OP_0, btcscript.OP_DATA_33, - 0x02, 0x40, 0x05, 0xc9, 0x45, 0xd8, 0x6a, 0xc6, - 0xb0, 0x1f, 0xb0, 0x42, 0x58, 0x34, 0x5a, 0xbe, - 0xa7, 0xa8, 0x45, 0xbd, 0x25, 0x68, 0x9e, 0xdb, - 0x72, 0x3d, 0x5a, 0xd4, 0x06, 0x8d, 0xdd, 0x30, - 0x36, // note this isn't a real tx - }, - addrhash: nil, - class: btcscript.ScriptStrange, - }, - {script: []byte{btcscript.OP_HASH160, btcscript.OP_DATA_20, - 0x63, 0xbc, 0xc5, 0x65, 0xf9, 0xe6, 0x8e, 0xe0, - 0x18, 0x9d, 0xd5, 0xcc, 0x67, 0xf1, 0xb0, 0xe5, - 0xf0, 0x2f, 0x45, 0xcb, - btcscript.OP_EQUAL, - }, - addrhash: []byte{0x63, 0xbc, 0xc5, 0x65, 0xf9, 0xe6, 0x8e, 0xe0, - 0x18, 0x9d, 0xd5, 0xcc, 0x67, 0xf1, 0xb0, 0xe5, - 0xf0, 0x2f, 0x45, 0xcb}, - class: btcscript.ScriptPayToScriptHash, - }, - {script: []byte{btcscript.OP_DATA_36, - 0x02, 0x40, 0x05, 0xc9, 0x45, 0xd8, 0x6a, 0xc6, - 0xb0, 0x1f, 0xb0, 0x42, 0x58, 0x34, 0x5a, 0xbe, - 0xb0, 0x1f, 0xb0, 0x42, 0x58, 0x34, 0x5a, 0xbe, - 0xb0, 0x1f, 0xb0, 0x42, 0x58, 0x34, 0x5a, 0xbe, - 0xa7, 0xa8, 0x45, 0xbd, - // note this isn't a real tx - }, - addrhash: nil, - class: btcscript.ScriptStrange, - }, - {script: []byte{}, - shouldFail: btcscript.StackErrUnknownAddress, - }, -} - -func TestAddresses(t *testing.T) { - for i, s := range addressTests { - class, addrhash, err := btcscript.ScriptToAddrHash(s.script) - if s.shouldFail != nil { - if err != s.shouldFail { - t.Errorf("Address test %v failed is err [%v] should be [%v]", i, err, s.shouldFail) - } - } else { - if err != nil { - t.Errorf("Address test %v failed err %v", i, err) - } else { - if !bytes.Equal(s.addrhash, addrhash) { - t.Errorf("Address test %v mismatch is [%v] want [%v]", i, addrhash, s.addrhash) - } - if s.class != class { - t.Errorf("Address test %v class mismatch is [%v] want [%v]", i, class, s.class) - } - } - } - - } -} - -type stringifyTest struct { - name string - scripttype btcscript.ScriptType - stringed string -} - -var stringifyTests = []stringifyTest{ - stringifyTest{ - name: "unknown", - scripttype: btcscript.ScriptUnknown, - stringed: "Unknown", - }, - stringifyTest{ - name: "addr", - scripttype: btcscript.ScriptAddr, - stringed: "Addr", - }, - stringifyTest{ - name: "pubkey", - scripttype: btcscript.ScriptPubKey, - stringed: "Pubkey", - }, - stringifyTest{ - name: "strange", - scripttype: btcscript.ScriptStrange, - stringed: "Strange", - }, - stringifyTest{ - name: "generation", - scripttype: btcscript.ScriptGeneration, - stringed: "Generation", - }, - stringifyTest{ - name: "not in enum", - scripttype: btcscript.ScriptType(255), - stringed: "Invalid", - }, -} - -func TestStringify(t *testing.T) { - for _, test := range stringifyTests { - typeString := test.scripttype.String() - if typeString != test.stringed { - t.Errorf("%s: got \"%s\" expected \"%s\"", test.name, - typeString, test.stringed) - } - } -} - -type multiSigTest struct { - script []byte - reqSigs int - addrhashes [][]byte - shouldFail error - class btcscript.ScriptType -} - -var multiSigTests = []multiSigTest{ - {script: []byte{}, - class: btcscript.ScriptUnknown, - shouldFail: btcscript.StackErrUnknownAddress, - }, - {script: []byte{btcscript.OP_DATA_65, - 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, - 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, - 0x1e, 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, - 0x2e, 0xca, 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, - 0x5c, 0xb2, 0xe0, 0xea, 0xdd, 0xfb, 0x84, 0xcc, - 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, - 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, - 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, - 0xa3, btcscript.OP_CHECKSIG}, - class: btcscript.ScriptUnknown, - shouldFail: btcscript.StackErrUnknownAddress, - }, - {script: []byte{ - btcscript.OP_1, btcscript.OP_DATA_65, - 0x04, 0xcc, 0x71, 0xeb, 0x30, 0xd6, 0x53, 0xc0, - 0xc3, 0x16, 0x39, 0x90, 0xc4, 0x7b, 0x97, 0x6f, - 0x3f, 0xb3, 0xf3, 0x7c, 0xcc, 0xdc, 0xbe, 0xdb, - 0x16, 0x9a, 0x1d, 0xfe, 0xf5, 0x8b, 0xbf, 0xbf, - 0xaf, 0xf7, 0xd8, 0xa4, 0x73, 0xe7, 0xe2, 0xe6, - 0xd3, 0x17, 0xb8, 0x7b, 0xaf, 0xe8, 0xbd, 0xe9, - 0x7e, 0x3c, 0xf8, 0xf0, 0x65, 0xde, 0xc0, 0x22, - 0xb5, 0x1d, 0x11, 0xfc, 0xdd, 0x0d, 0x34, 0x8a, - 0xc4, btcscript.OP_DATA_65, - 0x04, 0x61, 0xcb, 0xdc, 0xc5, 0x40, 0x9f, 0xb4, - 0xb4, 0xd4, 0x2b, 0x51, 0xd3, 0x33, 0x81, 0x35, - 0x4d, 0x80, 0xe5, 0x50, 0x07, 0x8c, 0xb5, 0x32, - 0xa3, 0x4b, 0xfa, 0x2f, 0xcf, 0xde, 0xb7, 0xd7, - 0x65, 0x19, 0xae, 0xcc, 0x62, 0x77, 0x0f, 0x5b, - 0x0e, 0x4e, 0xf8, 0x55, 0x19, 0x46, 0xd8, 0xa5, - 0x40, 0x91, 0x1a, 0xbe, 0x3e, 0x78, 0x54, 0xa2, - 0x6f, 0x39, 0xf5, 0x8b, 0x25, 0xc1, 0x53, 0x42, - 0xaf, btcscript.OP_2, btcscript.OP_CHECKMULTISIG}, - class: btcscript.ScriptMultiSig, - reqSigs: 1, - addrhashes: [][]byte{ - []byte{ - 0x66, 0x0d, 0x4e, 0xf3, 0xa7, 0x43, 0xe3, 0xe6, - 0x96, 0xad, 0x99, 0x03, 0x64, 0xe5, 0x55, 0xc2, - 0x71, 0xad, 0x50, 0x4b, - }, - []byte{ - 0x64, 0x1a, 0xd5, 0x05, 0x1e, 0xdd, 0x97, 0x02, - 0x9a, 0x00, 0x3f, 0xe9, 0xef, 0xb2, 0x93, 0x59, - 0xfc, 0xee, 0x40, 0x9d, - }, - }, - }, - - // from real tx 60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1, vout 0 - {script: []byte{ - btcscript.OP_1, btcscript.OP_DATA_65, - 0x04, 0xcc, 0x71, 0xeb, 0x30, 0xd6, 0x53, 0xc0, - 0xc3, 0x16, 0x39, 0x90, 0xc4, 0x7b, 0x97, 0x6f, - 0x3f, 0xb3, 0xf3, 0x7c, 0xcc, 0xdc, 0xbe, 0xdb, - 0x16, 0x9a, 0x1d, 0xfe, 0xf5, 0x8b, 0xbf, 0xbf, - 0xaf, 0xf7, 0xd8, 0xa4, 0x73, 0xe7, 0xe2, 0xe6, - 0xd3, 0x17, 0xb8, 0x7b, 0xaf, 0xe8, 0xbd, 0xe9, - 0x7e, 0x3c, 0xf8, 0xf0, 0x65, 0xde, 0xc0, 0x22, - 0xb5, 0x1d, 0x11, 0xfc, 0xdd, 0x0d, 0x34, 0x8a, - 0xc4, btcscript.OP_DATA_65, - 0x04, 0x61, 0xcb, 0xdc, 0xc5, 0x40, 0x9f, 0xb4, - 0xb4, 0xd4, 0x2b, 0x51, 0xd3, 0x33, 0x81, 0x35, - 0x4d, 0x80, 0xe5, 0x50, 0x07, 0x8c, 0xb5, 0x32, - 0xa3, 0x4b, 0xfa, 0x2f, 0xcf, 0xde, 0xb7, 0xd7, - 0x65, 0x19, 0xae, 0xcc, 0x62, 0x77, 0x0f, 0x5b, - 0x0e, 0x4e, 0xf8, 0x55, 0x19, 0x46, 0xd8, 0xa5, - 0x40, 0x91, 0x1a, 0xbe, 0x3e, 0x78, 0x54, 0xa2, - 0x6f, 0x39, 0xf5, 0x8b, 0x25, 0xc1, 0x53, 0x42, - 0xaf, btcscript.OP_2, btcscript.OP_CHECKMULTISIG}, - class: btcscript.ScriptMultiSig, - reqSigs: 1, - addrhashes: [][]byte{ - []byte{ - 0x66, 0x0d, 0x4e, 0xf3, 0xa7, 0x43, 0xe3, 0xe6, - 0x96, 0xad, 0x99, 0x03, 0x64, 0xe5, 0x55, 0xc2, - 0x71, 0xad, 0x50, 0x4b, - }, - []byte{ - 0x64, 0x1a, 0xd5, 0x05, 0x1e, 0xdd, 0x97, 0x02, - 0x9a, 0x00, 0x3f, 0xe9, 0xef, 0xb2, 0x93, 0x59, - 0xfc, 0xee, 0x40, 0x9d, - }, - }, - }, - - // from real tx: 691dd277dc0e90a462a3d652a1171686de49cf19067cd33c7df0392833fb986a, vout 0 - {script: []byte{ - btcscript.OP_1, btcscript.OP_DATA_65, - 0x1c, 0x22, 0x00, 0x00, 0x73, 0x53, 0x45, 0x58, - 0x57, 0x69, 0x6b, 0x69, 0x6c, 0x65, 0x61, 0x6b, - 0x73, 0x20, 0x43, 0x61, 0x62, 0x6c, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x20, 0x42, 0x61, 0x63, 0x6b, - 0x75, 0x70, 0x0a, 0x0a, 0x63, 0x61, 0x62, 0x6c, - 0x65, 0x67, 0x61, 0x74, 0x65, 0x2d, 0x32, 0x30, - 0x31, 0x30, 0x31, 0x32, 0x30, 0x34, 0x31, 0x38, - 0x31, 0x31, 0x2e, 0x37, 0x7a, 0x0a, 0x0a, 0x44, - 0x6f, btcscript.OP_DATA_65, - 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, - 0x77, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x72, 0x61, - 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x53, - 0x61, 0x74, 0x6f, 0x73, 0x68, 0x69, 0x20, 0x4e, - 0x61, 0x6b, 0x61, 0x6d, 0x6f, 0x74, 0x6f, 0x27, - 0x73, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, - 0x61, btcscript.OP_DATA_65, - 0x64, 0x20, 0x74, 0x6f, 0x6f, 0x6c, 0x20, 0x77, - 0x68, 0x69, 0x63, 0x68, 0x0a, 0x63, 0x61, 0x6e, - 0x20, 0x62, 0x65, 0x20, 0x66, 0x6f, 0x75, 0x6e, - 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x72, 0x61, - 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x20, 0x36, 0x63, 0x35, 0x33, 0x63, 0x64, 0x39, - 0x38, 0x37, 0x31, 0x31, 0x39, 0x65, 0x66, 0x37, - 0x39, 0x37, 0x64, 0x35, 0x61, 0x64, 0x63, 0x63, - 0x64, btcscript.OP_3, btcscript.OP_CHECKMULTISIG}, - class: btcscript.ScriptMultiSig, - reqSigs: 1, - addrhashes: [][]byte{ - []byte{ - 0x7c, 0xe9, 0x23, 0x01, 0x00, 0x75, 0x98, 0xc8, - 0xb9, 0x31, 0x5b, 0x49, 0x71, 0x21, 0xa0, 0x18, - 0x20, 0x90, 0xa3, 0x0c, - }, - []byte{ - 0x76, 0xf6, 0x95, 0x05, 0xb3, 0x9f, 0xba, 0x56, - 0x6d, 0xe8, 0x40, 0x89, 0xda, 0xd8, 0xbd, 0x35, - 0x01, 0xec, 0x47, 0xed, - }, - []byte{ - 0x7b, 0xfb, 0xfe, 0x5d, 0x66, 0x80, 0x22, 0x2e, - 0xe6, 0x38, 0xf9, 0x41, 0xdc, 0xfa, 0x61, 0x6d, - 0xd4, 0x5f, 0x11, 0xee, - }, - }, - }, - - // from real tx: 691dd277dc0e90a462a3d652a1171686de49cf19067cd33c7df0392833fb986a, vout 44 - {script: []byte{ - btcscript.OP_1, btcscript.OP_DATA_65, - 0x34, 0x63, 0x33, 0x65, 0x63, 0x32, 0x35, 0x39, - 0x63, 0x37, 0x34, 0x64, 0x61, 0x63, 0x65, 0x36, - 0x66, 0x64, 0x30, 0x38, 0x38, 0x62, 0x34, 0x34, - 0x63, 0x65, 0x66, 0x38, 0x63, 0x0a, 0x63, 0x36, - 0x36, 0x62, 0x63, 0x31, 0x39, 0x39, 0x36, 0x63, - 0x38, 0x62, 0x39, 0x34, 0x61, 0x33, 0x38, 0x31, - 0x31, 0x62, 0x33, 0x36, 0x35, 0x36, 0x31, 0x38, - 0x66, 0x65, 0x31, 0x65, 0x39, 0x62, 0x31, 0x62, - 0x35, btcscript.OP_DATA_65, - 0x36, 0x63, 0x61, 0x63, 0x63, 0x65, 0x39, 0x39, - 0x33, 0x61, 0x33, 0x39, 0x38, 0x38, 0x61, 0x34, - 0x36, 0x39, 0x66, 0x63, 0x63, 0x36, 0x64, 0x36, - 0x64, 0x61, 0x62, 0x66, 0x64, 0x0a, 0x32, 0x36, - 0x36, 0x33, 0x63, 0x66, 0x61, 0x39, 0x63, 0x66, - 0x34, 0x63, 0x30, 0x33, 0x63, 0x36, 0x30, 0x39, - 0x63, 0x35, 0x39, 0x33, 0x63, 0x33, 0x65, 0x39, - 0x31, 0x66, 0x65, 0x64, 0x65, 0x37, 0x30, 0x32, - 0x39, btcscript.OP_DATA_33, - 0x31, 0x32, 0x33, 0x64, 0x64, 0x34, 0x32, 0x64, - 0x32, 0x35, 0x36, 0x33, 0x39, 0x64, 0x33, 0x38, - 0x61, 0x36, 0x63, 0x66, 0x35, 0x30, 0x61, 0x62, - 0x34, 0x63, 0x64, 0x34, 0x34, 0x0a, 0x00, 0x00, - 0x00, btcscript.OP_3, btcscript.OP_CHECKMULTISIG}, - class: btcscript.ScriptMultiSig, - reqSigs: 1, - addrhashes: [][]byte{ - []byte{ - 0xfb, 0xf0, 0x08, 0x0b, 0xc5, 0xf9, 0xd7, 0x2a, - 0x9e, 0x64, 0x6f, 0x16, 0x46, 0x46, 0x1c, 0x43, - 0x19, 0xc3, 0xb6, 0xd4, - }, - []byte{ - 0xc6, 0x00, 0xe7, 0x69, 0xc3, 0xae, 0x20, 0xd4, - 0xa0, 0x50, 0x08, 0xd1, 0xe3, 0xad, 0x06, 0x33, - 0xf2, 0x7b, 0x77, 0xa2, - }, - []byte{ - 0xad, 0x34, 0x62, 0xcb, 0xa3, 0x5b, 0xee, 0x04, - 0xef, 0xd4, 0x20, 0x8c, 0xcd, 0x7f, 0x41, 0xf4, - 0xc8, 0x55, 0xf2, 0x73, - }, - }, - }, -} - -func TestMultiSigs(t *testing.T) { - for i, s := range multiSigTests { - class, reqSigs, addrhashes, err := btcscript.ScriptToAddrHashes(s.script) - if s.shouldFail != nil { - if err != s.shouldFail { - t.Errorf("MultiSig test %v failed is err [%v] should be [%v]", i, err, s.shouldFail) - } - } else { - if err != nil { - t.Errorf("MultiSig test %v failed err %v", i, err) - } else { - if s.class != class { - t.Errorf("MultiSig test %v class mismatch is [%v] want [%v]", i, class, s.class) - } - if len(addrhashes) != len(s.addrhashes) { - t.Errorf("MultiSig test %v num addrhashes expected is [%d] want [%d]", i, len(addrhashes), len(s.addrhashes)) - } - if reqSigs != s.reqSigs { - t.Errorf("MultiSig test %v reqSigs expected is [%d] want [%d]", i, reqSigs, s.reqSigs) - } - for j := 0; j < len(addrhashes); j++ { - if !bytes.Equal(s.addrhashes[j], addrhashes[j]) { - t.Errorf("MultiSig test %v addrhash %d mismatch is [%v] want [%v]", i, j, addrhashes[j], s.addrhashes[j]) - } - } - } - } - - } -} diff --git a/internal_test.go b/internal_test.go index 0d03b0f7..9d2def58 100644 --- a/internal_test.go +++ b/internal_test.go @@ -49,69 +49,6 @@ func TstSignatureScriptCustomReader(reader io.Reader, tx *btcwire.MsgTx, idx int hashType, privkey, compress) } -// Tests for internal error cases in ScriptToAddrHash. -// We pass bad format definitions to ScriptToAddrHash to make sure the internal -// checks work correctly. This is located in internal_test.go and not address.go -// because of the ridiculous amount of internal types/constants that would -// otherwise need to be exported here. - -type pkformatTest struct { - name string - format pkformat - script []byte - ty ScriptType - err error -} - -var TstPkFormats = []pkformatTest{ - pkformatTest{ - name: "bad offset", - format: pkformat{ - addrtype: ScriptAddr, - parsetype: scrNoAddr, - length: 4, - databytes: []pkbytes{{0, OP_1}, {1, OP_2}, {2, - OP_3}, /* wrong - too long */ {9, OP_4}}, - allowmore: true, - }, - script: []byte{OP_1, OP_2, OP_3, OP_4}, - err: StackErrInvalidAddrOffset, - }, - pkformatTest{ - name: "Bad parsetype", - format: pkformat{ - addrtype: ScriptAddr, - parsetype: 8, // invalid type - length: 4, - databytes: []pkbytes{{0, OP_1}, {1, OP_2}, {2, - OP_3}, /* wrong - too long */ {3, OP_4}}, - allowmore: true, - }, - script: []byte{OP_1, OP_2, OP_3, OP_4}, - err: StackErrInvalidParseType, - }, -} - -func TestBadPkFormat(t *testing.T) { - for _, test := range TstPkFormats { - ty, addr, err := scriptToAddrHashTemplate(test.script, - []pkformat{test.format}) - if err != nil { - if err != test.err { - t.Errorf("%s got error \"%v\". Was expecrting "+ - "\"%v\"", test.name, err, test.err) - } - continue - } - if ty != test.ty { - t.Errorf("%s: unexpected type \"%s\". Wanted \"%s\" (addr %v)", - test.name, ty, test.ty, addr) - continue - } - } - -} - // Internal tests for opcodde parsing with bad data templates. func TestParseOpcode(t *testing.T) { fakemap := make(map[byte]*opcode) diff --git a/script.go b/script.go index 8cf11391..627829f4 100644 --- a/script.go +++ b/script.go @@ -1200,35 +1200,3 @@ func CalcMultiSigStats(script []byte) (int, int, error) { numPubKeys := int(pops[len(pops)-2].opcode.value - (OP_1 - 1)) return numPubKeys, numSigs, nil } - -// CalcPkScriptAddrHashes returns the type of script as well as the required -// number of signatures and the hashes of the addresses. -func CalcPkScriptAddrHashes(script []byte) (ScriptClass, int, [][]byte) { - c := GetScriptClass(script) - switch c { - case ScriptHashTy: - fallthrough - case PubKeyTy: - fallthrough - case PubKeyHashTy: - _, addrHash, err := ScriptToAddrHash(script) - if err != nil { - return NonStandardTy, 0, nil - } - return c, 1, [][]byte{addrHash} - - case MultiSigTy: - _, reqSigs, addrHashes, err := ScriptToAddrHashes(script) - if err != nil { - return NonStandardTy, 0, nil - } - - return c, reqSigs, addrHashes - case NonStandardTy: - fallthrough - case NullDataTy: - fallthrough - default: - return NonStandardTy, 0, nil - } -} From e50681264bb8373b82eda9fa1a0416d110741592 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Tue, 7 Jan 2014 17:50:04 -0600 Subject: [PATCH 083/174] Add 100% test coverage for ExtractPkScriptAddrs. --- address_test.go | 366 ++++++++++++++++++++++++++++++++++++++++++++++ test_coverage.txt | 172 +++++++++++----------- 2 files changed, 450 insertions(+), 88 deletions(-) create mode 100644 address_test.go diff --git a/address_test.go b/address_test.go new file mode 100644 index 00000000..5de4c2a5 --- /dev/null +++ b/address_test.go @@ -0,0 +1,366 @@ +// Copyright (c) 2013 Conformal Systems LLC. +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. +package btcscript_test + +import ( + "encoding/hex" + "github.com/conformal/btcscript" + "github.com/conformal/btcutil" + "github.com/conformal/btcwire" + "reflect" + "testing" +) + +// decodeHex decodes the passed hex string and returns the resulting bytes. It +// panics if an error occurs. This is only used in the tests as a helper since +// the only way it can fail is if there is an error in the test source code. +func decodeHex(hexStr string) []byte { + b, err := hex.DecodeString(hexStr) + if err != nil { + panic("invalid hex string in test source: err " + err.Error() + + ", hex: " + hexStr) + } + + return b +} + +// newAddressPubKey returns a new btcutil.AddressPubKey from the provided +// serialized public key. It panics if an error occurs. This is only used in +// the tests as a helper since the only way it can fail is if there is an error +// in the test source code. +func newAddressPubKey(serializedPubKey []byte) btcutil.Address { + addr, err := btcutil.NewAddressPubKey(serializedPubKey, btcwire.MainNet) + if err != nil { + panic("invalid public key in test source") + } + + return addr +} + +// newAddressPubKeyHash returns a new btcutil.AddressPubKeyHash from the +// provided hash. It panics if an error occurs. This is only used in the tests +// as a helper since the only way it can fail is if there is an error in the +// test source code. +func newAddressPubKeyHash(pkHash []byte) btcutil.Address { + addr, err := btcutil.NewAddressPubKeyHash(pkHash, btcwire.MainNet) + if err != nil { + panic("invalid public key hash in test source") + } + + return addr +} + +// newAddressScriptHash returns a new btcutil.AddressScriptHash from the +// provided hash. It panics if an error occurs. This is only used in the tests +// as a helper since the only way it can fail is if there is an error in the +// test source code. +func newAddressScriptHash(scriptHash []byte) btcutil.Address { + addr, err := btcutil.NewAddressScriptHashFromHash(scriptHash, + btcwire.MainNet) + if err != nil { + panic("invalid script hash in test source") + } + + return addr +} + +// TestExtractPkScriptAddrs ensures that extracting the type, addresses, and +// number of required signatures from PkScripts works as intended. +func TestExtractPkScriptAddrs(t *testing.T) { + tests := []struct { + name string + script []byte + addrs []btcutil.Address + reqSigs int + class btcscript.ScriptClass + }{ + { + name: "standard p2pk with compressed pubkey (0x02)", + script: decodeHex("2102192d74d0cb94344c9569c2e7790157" + + "3d8d7903c3ebec3a957724895dca52c6b4ac"), + addrs: []btcutil.Address{ + newAddressPubKey(decodeHex("02192d74d0cb94344" + + "c9569c2e77901573d8d7903c3ebec3a95772" + + "4895dca52c6b4")), + }, + reqSigs: 1, + class: btcscript.PubKeyTy, + }, + { + name: "standard p2pk with uncompressed pubkey (0x04)", + script: decodeHex("410411db93e1dcdb8a016b49840f8c53bc" + + "1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb" + + "84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643" + + "f656b412a3ac"), + addrs: []btcutil.Address{ + newAddressPubKey(decodeHex("0411db93e1dcdb8a0" + + "16b49840f8c53bc1eb68a382e97b1482ecad" + + "7b148a6909a5cb2e0eaddfb84ccf9744464f" + + "82e160bfa9b8b64f9d4c03f999b8643f656b" + + "412a3")), + }, + reqSigs: 1, + class: btcscript.PubKeyTy, + }, + { + name: "standard p2pk with hybrid pubkey (0x06)", + script: decodeHex("4106192d74d0cb94344c9569c2e7790157" + + "3d8d7903c3ebec3a957724895dca52c6b40d45264838" + + "c0bd96852662ce6a847b197376830160c6d2eb5e6a4c" + + "44d33f453eac"), + addrs: []btcutil.Address{ + newAddressPubKey(decodeHex("06192d74d0cb94344" + + "c9569c2e77901573d8d7903c3ebec3a95772" + + "4895dca52c6b40d45264838c0bd96852662c" + + "e6a847b197376830160c6d2eb5e6a4c44d33" + + "f453e")), + }, + reqSigs: 1, + class: btcscript.PubKeyTy, + }, + { + name: "standard p2pk with compressed pubkey (0x03)", + script: decodeHex("2103b0bd634234abbb1ba1e986e884185c" + + "61cf43e001f9137f23c2c409273eb16e65ac"), + addrs: []btcutil.Address{ + newAddressPubKey(decodeHex("03b0bd634234abbb1" + + "ba1e986e884185c61cf43e001f9137f23c2c" + + "409273eb16e65")), + }, + reqSigs: 1, + class: btcscript.PubKeyTy, + }, + { + name: "2nd standard p2pk with uncompressed pubkey (0x04)", + script: decodeHex("4104b0bd634234abbb1ba1e986e884185c" + + "61cf43e001f9137f23c2c409273eb16e6537a576782e" + + "ba668a7ef8bd3b3cfb1edb7117ab65129b8a2e681f3c" + + "1e0908ef7bac"), + addrs: []btcutil.Address{ + newAddressPubKey(decodeHex("04b0bd634234abbb1" + + "ba1e986e884185c61cf43e001f9137f23c2c" + + "409273eb16e6537a576782eba668a7ef8bd3" + + "b3cfb1edb7117ab65129b8a2e681f3c1e090" + + "8ef7b")), + }, + reqSigs: 1, + class: btcscript.PubKeyTy, + }, + { + name: "standard p2pk with hybrid pubkey (0x07)", + script: decodeHex("4107b0bd634234abbb1ba1e986e884185c" + + "61cf43e001f9137f23c2c409273eb16e6537a576782e" + + "ba668a7ef8bd3b3cfb1edb7117ab65129b8a2e681f3c" + + "1e0908ef7bac"), + addrs: []btcutil.Address{ + newAddressPubKey(decodeHex("07b0bd634234abbb1" + + "ba1e986e884185c61cf43e001f9137f23c2c" + + "409273eb16e6537a576782eba668a7ef8bd3" + + "b3cfb1edb7117ab65129b8a2e681f3c1e090" + + "8ef7b")), + }, + reqSigs: 1, + class: btcscript.PubKeyTy, + }, + { + name: "standard p2pkh", + script: decodeHex("76a914ad06dd6ddee55cbca9a9e3713bd7" + + "587509a3056488ac"), + addrs: []btcutil.Address{ + newAddressPubKeyHash(decodeHex("ad06dd6ddee55" + + "cbca9a9e3713bd7587509a30564")), + }, + reqSigs: 1, + class: btcscript.PubKeyHashTy, + }, + { + name: "standard p2sh", + script: decodeHex("a91463bcc565f9e68ee0189dd5cc67f1b0" + + "e5f02f45cb87"), + addrs: []btcutil.Address{ + newAddressScriptHash(decodeHex("63bcc565f9e68" + + "ee0189dd5cc67f1b0e5f02f45cb")), + }, + reqSigs: 1, + class: btcscript.ScriptHashTy, + }, + // from real tx 60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1, vout 0 + { + name: "standard 1 of 2 multisig", + script: decodeHex("514104cc71eb30d653c0c3163990c47b97" + + "6f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473" + + "e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11" + + "fcdd0d348ac4410461cbdcc5409fb4b4d42b51d33381" + + "354d80e550078cb532a34bfa2fcfdeb7d76519aecc62" + + "770f5b0e4ef8551946d8a540911abe3e7854a26f39f5" + + "8b25c15342af52ae"), + addrs: []btcutil.Address{ + newAddressPubKey(decodeHex("04cc71eb30d653c0c" + + "3163990c47b976f3fb3f37cccdcbedb169a1" + + "dfef58bbfbfaff7d8a473e7e2e6d317b87ba" + + "fe8bde97e3cf8f065dec022b51d11fcdd0d3" + + "48ac4")), + newAddressPubKey(decodeHex("0461cbdcc5409fb4b" + + "4d42b51d33381354d80e550078cb532a34bf" + + "a2fcfdeb7d76519aecc62770f5b0e4ef8551" + + "946d8a540911abe3e7854a26f39f58b25c15" + + "342af")), + }, + reqSigs: 1, + class: btcscript.MultiSigTy, + }, + // from real tx d646f82bd5fbdb94a36872ce460f97662b80c3050ad3209bef9d1e398ea277ab, vin 1 + { + name: "standard 2 of 3 multisig", + script: decodeHex("524104cb9c3c222c5f7a7d3b9bd152f363" + + "a0b6d54c9eb312c4d4f9af1e8551b6c421a6a4ab0e29" + + "105f24de20ff463c1c91fcf3bf662cdde4783d4799f7" + + "87cb7c08869b4104ccc588420deeebea22a7e900cc8b" + + "68620d2212c374604e3487ca08f1ff3ae12bdc639514" + + "d0ec8612a2d3c519f084d9a00cbbe3b53d071e9b09e7" + + "1e610b036aa24104ab47ad1939edcb3db65f7fedea62" + + "bbf781c5410d3f22a7a3a56ffefb2238af8627363bdf" + + "2ed97c1f89784a1aecdb43384f11d2acc64443c7fc29" + + "9cef0400421a53ae"), + addrs: []btcutil.Address{ + newAddressPubKey(decodeHex("04cb9c3c222c5f7a7" + + "d3b9bd152f363a0b6d54c9eb312c4d4f9af1" + + "e8551b6c421a6a4ab0e29105f24de20ff463" + + "c1c91fcf3bf662cdde4783d4799f787cb7c0" + + "8869b")), + newAddressPubKey(decodeHex("04ccc588420deeebe" + + "a22a7e900cc8b68620d2212c374604e3487c" + + "a08f1ff3ae12bdc639514d0ec8612a2d3c51" + + "9f084d9a00cbbe3b53d071e9b09e71e610b0" + + "36aa2")), + newAddressPubKey(decodeHex("04ab47ad1939edcb3" + + "db65f7fedea62bbf781c5410d3f22a7a3a56" + + "ffefb2238af8627363bdf2ed97c1f89784a1" + + "aecdb43384f11d2acc64443c7fc299cef040" + + "0421a")), + }, + reqSigs: 2, + class: btcscript.MultiSigTy, + }, + + // The below are nonstandard script due to things such as + // invalid pubkeys, failure to parse, and not being of a + // standard form. + + { + name: "p2pk with uncompressed pk missing OP_CHECKSIG", + script: decodeHex("410411db93e1dcdb8a016b49840f8c53bc" + + "1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb" + + "84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643" + + "f656b412a3"), + addrs: nil, + reqSigs: 0, + class: btcscript.NonStandardTy, + }, + { + name: "valid signature from a sigscript - no addresses", + script: decodeHex("47304402204e45e16932b8af514961a1d3" + + "a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220" + + "181522ec8eca07de4860a4acdd12909d831cc56cbbac" + + "4622082221a8768d1d0901"), + addrs: nil, + reqSigs: 0, + class: btcscript.NonStandardTy, + }, + // Note the technically the pubkey is the second item on the + // stack, but since the address extraction intentionally only + // works with standard PkScripts, this should not return any + // addresses. + { + name: "valid sigscript to reedeem p2pk - no addresses", + script: decodeHex("493046022100ddc69738bf2336318e4e04" + + "1a5a77f305da87428ab1606f023260017854350ddc02" + + "2100817af09d2eec36862d16009852b7e3a0f6dd7659" + + "8290b7834e1453660367e07a014104cd4240c198e125" + + "23b6f9cb9f5bed06de1ba37e96a1bbd13745fcf9d11c" + + "25b1dff9a519675d198804ba9962d3eca2d5937d58e5" + + "a75a71042d40388a4d307f887d"), + addrs: nil, + reqSigs: 0, + class: btcscript.NonStandardTy, + }, + // from real tx 691dd277dc0e90a462a3d652a1171686de49cf19067cd33c7df0392833fb986a, vout 0 + // invalid public keys + { + name: "1 of 3 multisig with invalid pubkeys", + script: decodeHex("51411c2200007353455857696b696c6561" + + "6b73204361626c6567617465204261636b75700a0a63" + + "61626c65676174652d3230313031323034313831312e" + + "377a0a0a446f41776e6c6f61642074686520666f6c6c" + + "6f77696e67207472616e73616374696f6e7320776974" + + "68205361746f736869204e616b616d6f746f27732064" + + "6f776e6c6f61416420746f6f6c2077686963680a6361" + + "6e20626520666f756e6420696e207472616e73616374" + + "696f6e20366335336364393837313139656637393764" + + "35616463636453ae"), + addrs: []btcutil.Address{}, + reqSigs: 1, + class: btcscript.MultiSigTy, + }, + // from real tx: 691dd277dc0e90a462a3d652a1171686de49cf19067cd33c7df0392833fb986a, vout 44 + // invalid public keys + { + name: "1 of 3 multisig with invalid pubkeys 2", + script: decodeHex("5141346333656332353963373464616365" + + "36666430383862343463656638630a63363662633139" + + "39366338623934613338313162333635363138666531" + + "65396231623541366361636365393933613339383861" + + "34363966636336643664616266640a32363633636661" + + "39636634633033633630396335393363336539316665" + + "64653730323921313233646434326432353633396433" + + "38613663663530616234636434340a00000053ae"), + addrs: []btcutil.Address{}, + reqSigs: 1, + class: btcscript.MultiSigTy, + }, + { + name: "empty script", + script: []byte{}, + addrs: nil, + reqSigs: 0, + class: btcscript.NonStandardTy, + }, + { + name: "script that does not parse", + script: []byte{btcscript.OP_DATA_45}, + addrs: nil, + reqSigs: 0, + class: btcscript.NonStandardTy, + }, + } + + t.Logf("Running %d tests.", len(tests)) + for i, test := range tests { + class, addrs, reqSigs, err := btcscript.ExtractPkScriptAddrs( + test.script, btcwire.MainNet) + if err != nil { + } + + if !reflect.DeepEqual(addrs, test.addrs) { + t.Errorf("ExtractPkScriptAddrs #%d (%s) unexpected "+ + "addresses\ngot %v\nwant %v", i, test.name, + addrs, test.addrs) + continue + } + + if reqSigs != test.reqSigs { + t.Errorf("ExtractPkScriptAddrs #%d (%s) unexpected "+ + "number of required signatures - got %d, "+ + "want %d", i, test.name, reqSigs, test.reqSigs) + continue + } + + if class != test.class { + t.Errorf("ExtractPkScriptAddrs #%d (%s) unexpected "+ + "script type - got %s, want %s", i, test.name, + class, test.class) + continue + } + } +} diff --git a/test_coverage.txt b/test_coverage.txt index 4478ce22..a115226d 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -1,159 +1,155 @@ -github.com/conformal/btcscript/address.go scriptToAddrHashTemplate 100.00% (44/44) github.com/conformal/btcscript/script.go Script.Step 100.00% (37/37) github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (30/30) +github.com/conformal/btcscript/address.go ExtractPkScriptAddrs 100.00% (27/27) github.com/conformal/btcscript/script.go CalcScriptInfo 100.00% (25/25) github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23) -github.com/conformal/btcscript/script.go NewScript 100.00% (21/21) github.com/conformal/btcscript/stack.go asInt 100.00% (21/21) +github.com/conformal/btcscript/script.go NewScript 100.00% (21/21) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (16/16) github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (16/16) github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (14/14) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) -github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) -github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) +github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) -github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) +github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) +github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) +github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) -github.com/conformal/btcscript/script.go PayToAddrScript 100.00% (8/8) +github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) +github.com/conformal/btcscript/script.go PayToAddrScript 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) -github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/script.go unparseScript 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) github.com/conformal/btcscript/script.go typeOfScript 100.00% (7/7) +github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) -github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) -github.com/conformal/btcscript/script.go isNullData 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) -github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) -github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) -github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) +github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) -github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) -github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) +github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) +github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) +github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) +github.com/conformal/btcscript/script.go isNullData 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) +github.com/conformal/btcscript/script.go ScriptClass.String 100.00% (3/3) github.com/conformal/btcscript/script.go setStack 100.00% (3/3) -github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) +github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) -github.com/conformal/btcscript/script.go ScriptClass.String 100.00% (3/3) -github.com/conformal/btcscript/script.go PayToScriptHashScript 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) -github.com/conformal/btcscript/address.go ScriptToAddrHash 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) github.com/conformal/btcscript/script.go PayToPubKeyHashScript 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) -github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) -github.com/conformal/btcscript/opcode.go init 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) -github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) -github.com/conformal/btcscript/log.go init 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) +github.com/conformal/btcscript/script.go PayToScriptHashScript 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) -github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) +github.com/conformal/btcscript/opcode.go init 100.00% (1/1) github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) +github.com/conformal/btcscript/log.go init 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) +github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) +github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) +github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) +github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.28% (57/58) -github.com/conformal/btcscript/address.go ScriptToAddrHashes 90.91% (10/11) github.com/conformal/btcscript/opcode.go opcodeCheckSig 90.62% (29/32) github.com/conformal/btcscript/script.go expectedInputs 85.71% (6/7) github.com/conformal/btcscript/script.go calcScriptHash 82.05% (32/39) github.com/conformal/btcscript/script.go Script.CheckErrorCondition 78.57% (11/14) github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) -github.com/conformal/btcscript/script.go CalcPkScriptAddrHashes 0.00% (0/15) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/10) github.com/conformal/btcscript/script.go CalcMultiSigStats 0.00% (0/8) github.com/conformal/btcscript/script.go IsPushOnlyScript 0.00% (0/4) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) github.com/conformal/btcscript/log.go UseLogger 0.00% (0/1) -github.com/conformal/btcscript --------------------------- 93.80% (999/1065) +github.com/conformal/btcscript --------------------------- 95.08% (967/1017) From 565f11409c4a1fca39814e9f616a3dada8ca78c7 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 8 Jan 2014 23:47:23 -0600 Subject: [PATCH 084/174] Add 2014 to copyright dates. --- LICENSE | 2 +- address.go | 2 +- address_test.go | 2 +- doc.go | 2 +- internal_test.go | 2 +- log.go | 2 +- opcode.go | 2 +- opcode_test.go | 2 +- script.go | 2 +- script_test.go | 2 +- stack.go | 2 +- stack_test.go | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/LICENSE b/LICENSE index 62a53cea..67cfe82f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2013 Conformal Systems LLC. +Copyright (c) 2013-2014 Conformal Systems LLC. Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above diff --git a/address.go b/address.go index caeb680a..db4b274d 100644 --- a/address.go +++ b/address.go @@ -1,4 +1,4 @@ -// Copyright (c) 2013 Conformal Systems LLC. +// Copyright (c) 2013-2014 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. diff --git a/address_test.go b/address_test.go index 5de4c2a5..698fcce5 100644 --- a/address_test.go +++ b/address_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2013 Conformal Systems LLC. +// Copyright (c) 2013-2014 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. package btcscript_test diff --git a/doc.go b/doc.go index 4b50547f..aa054ddc 100644 --- a/doc.go +++ b/doc.go @@ -1,4 +1,4 @@ -// Copyright (c) 2013 Conformal Systems LLC. +// Copyright (c) 2013-2014 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. diff --git a/internal_test.go b/internal_test.go index 9d2def58..72448c7d 100644 --- a/internal_test.go +++ b/internal_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2013 Conformal Systems LLC. +// Copyright (c) 2013-2014 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. diff --git a/log.go b/log.go index 4b938bd4..b1ca42a0 100644 --- a/log.go +++ b/log.go @@ -1,4 +1,4 @@ -// Copyright (c) 2013 Conformal Systems LLC. +// Copyright (c) 2013-2014 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. diff --git a/opcode.go b/opcode.go index c4baac02..2d54d946 100644 --- a/opcode.go +++ b/opcode.go @@ -1,4 +1,4 @@ -// Copyright (c) 2013 Conformal Systems LLC. +// Copyright (c) 2013-2014 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. diff --git a/opcode_test.go b/opcode_test.go index 0c446b0f..3870b6ce 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2013 Conformal Systems LLC. +// Copyright (c) 2013-2014 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. diff --git a/script.go b/script.go index 627829f4..2a8a9fcb 100644 --- a/script.go +++ b/script.go @@ -1,4 +1,4 @@ -// Copyright (c) 2013 Conformal Systems LLC. +// Copyright (c) 2013-2014 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. diff --git a/script_test.go b/script_test.go index c98bb188..da17743f 100644 --- a/script_test.go +++ b/script_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2013 Conformal Systems LLC. +// Copyright (c) 2013-2014 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. diff --git a/stack.go b/stack.go index b09b2322..ffc30429 100644 --- a/stack.go +++ b/stack.go @@ -1,4 +1,4 @@ -// Copyright (c) 2013 Conformal Systems LLC. +// Copyright (c) 2013-2014 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. diff --git a/stack_test.go b/stack_test.go index 0bf76c03..b9e4059d 100644 --- a/stack_test.go +++ b/stack_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2013 Conformal Systems LLC. +// Copyright (c) 2013-2014 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. From b11f1620e26e0149faedb78d9037344e97e2df71 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 17 Jan 2014 09:32:22 -0600 Subject: [PATCH 085/174] Remove warnings for errors that are returned. ok @owainga. --- opcode.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/opcode.go b/opcode.go index 2d54d946..67cbebbb 100644 --- a/opcode.go +++ b/opcode.go @@ -1723,7 +1723,6 @@ func opcodeCheckSig(op *parsedOpcode, s *Script) error { pubKey, err := btcec.ParsePubKey(pkStr, btcec.S256()) if err != nil { - log.Warnf("can't parse public key from string: %v", err) return err } @@ -1734,7 +1733,6 @@ func opcodeCheckSig(op *parsedOpcode, s *Script) error { signature, err = btcec.ParseSignature(sigStr, btcec.S256()) } if err != nil { - log.Warnf("can't parse signature from string: %v", err) return err } @@ -1745,10 +1743,6 @@ func opcodeCheckSig(op *parsedOpcode, s *Script) error { signature.R, signature.S, spew.Sdump(hash)) })) ok := ecdsa.Verify(pubKey, hash, signature.R, signature.S) - if !ok { - log.Warnf("ecdsa.Verify valid: %v", ok) - } - s.dstack.PushBool(ok) return nil } From e8881196d6b291753b956c9294ab066a891e2a61 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Tue, 4 Feb 2014 03:13:23 +0000 Subject: [PATCH 086/174] Fix a number of bugs in signature checking When given badly formatted signature or pubkeys like in block 0000000000000001e4241fd0b3469a713f41c5682605451c05d3033288fb2244, transaction fd9b541d23f6e9bddb34ede15c7684eeec36231118796b691ae525f95578acf1 we could fail on strange scripts because we returned an error instead of failing the opcode and putting a FALSE on the stack. Fixes chainfork issue on the aforementioned block. --- opcode.go | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/opcode.go b/opcode.go index 67cbebbb..e182c69f 100644 --- a/opcode.go +++ b/opcode.go @@ -1723,7 +1723,8 @@ func opcodeCheckSig(op *parsedOpcode, s *Script) error { pubKey, err := btcec.ParsePubKey(pkStr, btcec.S256()) if err != nil { - return err + s.dstack.PushBool(false) + return nil } var signature *btcec.Signature @@ -1733,7 +1734,8 @@ func opcodeCheckSig(op *parsedOpcode, s *Script) error { signature, err = btcec.ParseSignature(sigStr, btcec.S256()) } if err != nil { - return err + s.dstack.PushBool(false) + return nil } log.Tracef("%v", newLogClosure(func() string { @@ -1798,32 +1800,38 @@ func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error { nsig := int(numSignatures.Int64()) sigStrings := make([][]byte, nsig) - signatures := make([]*btcec.Signature, nsig) - for i := range signatures { + signatures := make([]*btcec.Signature, 0, nsig) + for i := range sigStrings { sigStrings[i], err = s.dstack.PopByteArray() if err != nil { return err } + var sig *btcec.Signature // skip off the last byte for hashtype if s.der { - signatures[i], err = + sig, err = btcec.ParseDERSignature( sigStrings[i][:len(sigStrings[i])-1], btcec.S256()) } else { - signatures[i], err = + sig, err = btcec.ParseSignature( sigStrings[i][:len(sigStrings[i])-1], btcec.S256()) } - if err != nil { - return err + if err == nil { + signatures = append(signatures, sig) } } // bug in bitcoind mean we pop one more stack value than should be used. _, err = s.dstack.PopByteArray() if err != nil { + return err + } + + if len(signatures) == 0 { + s.dstack.PushBool(false) return nil } From 13ba8607f73512ae8627e050f1bfbb7fc0f96850 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Tue, 4 Feb 2014 11:22:51 -0600 Subject: [PATCH 087/174] Gofmt. --- opcode.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opcode.go b/opcode.go index e182c69f..bee36f85 100644 --- a/opcode.go +++ b/opcode.go @@ -1809,12 +1809,12 @@ func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error { var sig *btcec.Signature // skip off the last byte for hashtype if s.der { - sig, err = + sig, err = btcec.ParseDERSignature( sigStrings[i][:len(sigStrings[i])-1], btcec.S256()) } else { - sig, err = + sig, err = btcec.ParseSignature( sigStrings[i][:len(sigStrings[i])-1], btcec.S256()) From 971fbf8b28711c26c939833bdf53ab286cde02a4 Mon Sep 17 00:00:00 2001 From: David Hill Date: Tue, 4 Feb 2014 16:18:37 -0500 Subject: [PATCH 088/174] gofmt --- internal_test.go | 908 +++++++++++++++++++++++------------------------ opcode_test.go | 8 +- script.go | 18 +- script_test.go | 254 ++++++------- 4 files changed, 594 insertions(+), 594 deletions(-) diff --git a/internal_test.go b/internal_test.go index 72448c7d..5ce611b3 100644 --- a/internal_test.go +++ b/internal_test.go @@ -88,7 +88,7 @@ type popTest struct { } var popTests = []popTest{ - popTest{ + { name: "OP_FALSE", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_FALSE], @@ -96,7 +96,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_FALSE long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_FALSE], @@ -104,7 +104,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_1 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_1], @@ -112,7 +112,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_1", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_1], @@ -120,7 +120,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_1 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_1], @@ -128,7 +128,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_2 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_2], @@ -136,7 +136,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_2", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_2], @@ -144,7 +144,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_2 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_2], @@ -152,7 +152,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_3 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_3], @@ -160,7 +160,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_3", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_3], @@ -168,7 +168,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_3 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_3], @@ -176,7 +176,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_4 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_4], @@ -184,7 +184,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_4", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_4], @@ -192,7 +192,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_4 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_4], @@ -200,7 +200,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_5 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_5], @@ -208,7 +208,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_5", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_5], @@ -216,7 +216,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_5 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_5], @@ -224,7 +224,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_6 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_6], @@ -232,7 +232,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_6", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_6], @@ -240,7 +240,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_6 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_6], @@ -248,7 +248,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_7 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_7], @@ -256,7 +256,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_7", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_7], @@ -264,7 +264,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_7 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_7], @@ -272,7 +272,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_8 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_8], @@ -280,7 +280,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_8", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_8], @@ -288,7 +288,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_8 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_8], @@ -296,7 +296,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_9 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_9], @@ -304,7 +304,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_9", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_9], @@ -312,7 +312,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_9 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_9], @@ -320,7 +320,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_10 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_10], @@ -328,7 +328,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_10", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_10], @@ -336,7 +336,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_10 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_10], @@ -344,7 +344,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_11 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_11], @@ -352,7 +352,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_11", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_11], @@ -360,7 +360,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_11 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_11], @@ -368,7 +368,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_12 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_12], @@ -376,7 +376,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_12", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_12], @@ -384,7 +384,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_12 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_12], @@ -392,7 +392,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_13 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_13], @@ -400,7 +400,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_13", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_13], @@ -408,7 +408,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_13 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_13], @@ -416,7 +416,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_14 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_14], @@ -424,7 +424,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_14", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_14], @@ -432,7 +432,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_14 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_14], @@ -440,7 +440,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_15 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_15], @@ -448,7 +448,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_15", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_15], @@ -456,7 +456,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_15 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_15], @@ -464,7 +464,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_16 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_16], @@ -472,7 +472,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_16", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_16], @@ -480,7 +480,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_16 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_16], @@ -488,7 +488,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_17 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_17], @@ -496,7 +496,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_17", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_17], @@ -504,7 +504,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_17 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_17], @@ -512,7 +512,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_18 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_18], @@ -520,7 +520,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_18", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_18], @@ -528,7 +528,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_18 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_18], @@ -536,7 +536,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_19 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_19], @@ -544,7 +544,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_19", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_19], @@ -552,7 +552,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_19 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_19], @@ -560,7 +560,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_20 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_20], @@ -568,7 +568,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_20", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_20], @@ -576,7 +576,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_20 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_20], @@ -584,7 +584,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_21 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_21], @@ -592,7 +592,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_21", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_21], @@ -600,7 +600,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_21 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_21], @@ -608,7 +608,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_22 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_22], @@ -616,7 +616,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_22", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_22], @@ -624,7 +624,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_22 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_22], @@ -632,7 +632,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_23 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_23], @@ -640,7 +640,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_23", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_23], @@ -648,7 +648,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_23 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_23], @@ -656,7 +656,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_24 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_24], @@ -664,7 +664,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_24", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_24], @@ -672,7 +672,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_24 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_24], @@ -680,7 +680,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_25 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_25], @@ -688,7 +688,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_25", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_25], @@ -696,7 +696,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_25 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_25], @@ -704,7 +704,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_26 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_26], @@ -712,7 +712,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_26", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_26], @@ -720,7 +720,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_26 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_26], @@ -728,7 +728,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_27 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_27], @@ -736,7 +736,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_27", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_27], @@ -744,7 +744,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_27 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_27], @@ -752,7 +752,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_28 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_28], @@ -760,7 +760,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_28", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_28], @@ -768,7 +768,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_28 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_28], @@ -776,7 +776,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_29 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_29], @@ -784,7 +784,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_29", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_29], @@ -792,7 +792,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_29 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_29], @@ -800,7 +800,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_30 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_30], @@ -808,7 +808,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_30", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_30], @@ -816,7 +816,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_30 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_30], @@ -824,7 +824,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_31 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_31], @@ -832,7 +832,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_31", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_31], @@ -840,7 +840,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_31 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_31], @@ -848,7 +848,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_32 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_32], @@ -856,7 +856,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_32", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_32], @@ -864,7 +864,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_32 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_32], @@ -872,7 +872,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_33 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_33], @@ -880,7 +880,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_33", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_33], @@ -888,7 +888,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_33 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_33], @@ -896,7 +896,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_34 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_34], @@ -904,7 +904,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_34", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_34], @@ -912,7 +912,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_34 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_34], @@ -920,7 +920,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_35 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_35], @@ -928,7 +928,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_35", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_35], @@ -936,7 +936,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_35 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_35], @@ -944,7 +944,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_36 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_36], @@ -952,7 +952,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_36", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_36], @@ -960,7 +960,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_36 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_36], @@ -968,7 +968,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_37 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_37], @@ -976,7 +976,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_37", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_37], @@ -984,7 +984,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_37 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_37], @@ -992,7 +992,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_38 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_38], @@ -1000,7 +1000,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_38", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_38], @@ -1008,7 +1008,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_38 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_38], @@ -1016,7 +1016,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_39 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_39], @@ -1024,7 +1024,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_39", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_39], @@ -1032,7 +1032,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_39 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_39], @@ -1040,7 +1040,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_40 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_40], @@ -1048,7 +1048,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_40", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_40], @@ -1056,7 +1056,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_40 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_40], @@ -1064,7 +1064,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_41 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_41], @@ -1072,7 +1072,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_41", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_41], @@ -1080,7 +1080,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_41 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_41], @@ -1088,7 +1088,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_42 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_42], @@ -1096,7 +1096,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_42", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_42], @@ -1104,7 +1104,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_42 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_42], @@ -1112,7 +1112,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_43 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_43], @@ -1120,7 +1120,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_43", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_43], @@ -1128,7 +1128,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_43 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_43], @@ -1136,7 +1136,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_44 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_44], @@ -1144,7 +1144,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_44", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_44], @@ -1152,7 +1152,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_44 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_44], @@ -1160,7 +1160,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_45 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_45], @@ -1168,7 +1168,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_45", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_45], @@ -1176,7 +1176,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_45 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_45], @@ -1184,7 +1184,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_46 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_46], @@ -1192,7 +1192,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_46", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_46], @@ -1200,7 +1200,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_46 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_46], @@ -1208,7 +1208,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_47 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_47], @@ -1216,7 +1216,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_47", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_47], @@ -1224,7 +1224,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_47 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_47], @@ -1232,7 +1232,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_48 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_48], @@ -1240,7 +1240,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_48", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_48], @@ -1248,7 +1248,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_48 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_48], @@ -1256,7 +1256,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_49 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_49], @@ -1264,7 +1264,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_49", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_49], @@ -1272,7 +1272,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_49 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_49], @@ -1280,7 +1280,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_50 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_50], @@ -1288,7 +1288,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_50", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_50], @@ -1296,7 +1296,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_50 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_50], @@ -1304,7 +1304,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_51 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_51], @@ -1312,7 +1312,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_51", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_51], @@ -1320,7 +1320,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_51 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_51], @@ -1328,7 +1328,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_52 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_52], @@ -1336,7 +1336,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_52", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_52], @@ -1344,7 +1344,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_52 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_52], @@ -1352,7 +1352,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_53 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_53], @@ -1360,7 +1360,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_53", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_53], @@ -1368,7 +1368,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_53 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_53], @@ -1376,7 +1376,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_54 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_54], @@ -1384,7 +1384,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_54", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_54], @@ -1392,7 +1392,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_54 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_54], @@ -1400,7 +1400,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_55 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_55], @@ -1408,7 +1408,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_55", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_55], @@ -1416,7 +1416,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_55 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_55], @@ -1424,7 +1424,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_56 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_56], @@ -1432,7 +1432,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_56", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_56], @@ -1440,7 +1440,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_56 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_56], @@ -1448,7 +1448,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_57 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_57], @@ -1456,7 +1456,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_57", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_57], @@ -1464,7 +1464,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_57 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_57], @@ -1472,7 +1472,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_58 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_58], @@ -1480,7 +1480,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_58", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_58], @@ -1488,7 +1488,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_58 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_58], @@ -1496,7 +1496,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_59 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_59], @@ -1504,7 +1504,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_59", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_59], @@ -1512,7 +1512,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_59 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_59], @@ -1520,7 +1520,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_60 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_60], @@ -1528,7 +1528,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_60", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_60], @@ -1536,7 +1536,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_60 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_60], @@ -1544,7 +1544,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_61 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_61], @@ -1552,7 +1552,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_61", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_61], @@ -1560,7 +1560,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_61 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_61], @@ -1568,7 +1568,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_62 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_62], @@ -1576,7 +1576,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_62", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_62], @@ -1584,7 +1584,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_62 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_62], @@ -1592,7 +1592,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_63 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_63], @@ -1600,7 +1600,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_63", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_63], @@ -1608,7 +1608,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_63 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_63], @@ -1616,7 +1616,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_64 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_64], @@ -1624,7 +1624,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_64", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_64], @@ -1632,7 +1632,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_64 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_64], @@ -1640,7 +1640,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_65 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_65], @@ -1648,7 +1648,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_65", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_65], @@ -1656,7 +1656,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_65 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_65], @@ -1664,7 +1664,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_66 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_66], @@ -1672,7 +1672,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_66", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_66], @@ -1680,7 +1680,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_66 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_66], @@ -1688,7 +1688,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_67 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_67], @@ -1696,7 +1696,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_67", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_67], @@ -1704,7 +1704,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_67 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_67], @@ -1712,7 +1712,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_68 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_68], @@ -1720,7 +1720,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_68", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_68], @@ -1728,7 +1728,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_68 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_68], @@ -1736,7 +1736,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_69 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_69], @@ -1744,7 +1744,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_69", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_69], @@ -1752,7 +1752,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_69 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_69], @@ -1760,7 +1760,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_70 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_70], @@ -1768,7 +1768,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_70", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_70], @@ -1776,7 +1776,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_70 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_70], @@ -1784,7 +1784,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_71 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_71], @@ -1792,7 +1792,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_71", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_71], @@ -1800,7 +1800,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_71 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_71], @@ -1808,7 +1808,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_72 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_72], @@ -1816,7 +1816,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_72", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_72], @@ -1824,7 +1824,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_72 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_72], @@ -1832,7 +1832,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_73 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_73], @@ -1840,7 +1840,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_73", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_73], @@ -1848,7 +1848,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_73 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_73], @@ -1856,7 +1856,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_74 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_74], @@ -1864,7 +1864,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_74", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_74], @@ -1872,7 +1872,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_74 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_74], @@ -1880,7 +1880,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_75 short", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_75], @@ -1888,7 +1888,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DATA_75", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_75], @@ -1896,7 +1896,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DATA_75 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DATA_75], @@ -1904,7 +1904,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_PUSHDATA1", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_PUSHDATA1], @@ -1912,7 +1912,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_PUSHDATA2", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_PUSHDATA2], @@ -1920,7 +1920,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_PUSHDATA4", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_PUSHDATA1], @@ -1928,7 +1928,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_1NEGATE", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_1NEGATE], @@ -1936,7 +1936,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_1NEGATE long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_1NEGATE], @@ -1944,7 +1944,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_RESERVED", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_RESERVED], @@ -1952,7 +1952,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_RESERVED long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_RESERVED], @@ -1960,7 +1960,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_TRUE", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_TRUE], @@ -1968,7 +1968,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_TRUE long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_TRUE], @@ -1976,7 +1976,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_2", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_2], @@ -1984,7 +1984,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_2 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_2], @@ -1992,7 +1992,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_2", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_2], @@ -2000,7 +2000,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_2 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_2], @@ -2008,7 +2008,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_3", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_3], @@ -2016,7 +2016,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_3 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_3], @@ -2024,7 +2024,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_4", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_4], @@ -2032,7 +2032,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_4 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_4], @@ -2040,7 +2040,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_5", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_5], @@ -2048,7 +2048,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_5 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_5], @@ -2056,7 +2056,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_6", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_6], @@ -2064,7 +2064,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_6 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_6], @@ -2072,7 +2072,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_7", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_7], @@ -2080,7 +2080,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_7 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_7], @@ -2088,7 +2088,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_8", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_8], @@ -2096,7 +2096,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_8 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_8], @@ -2104,7 +2104,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_9", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_9], @@ -2112,7 +2112,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_9 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_9], @@ -2120,7 +2120,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_10", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_10], @@ -2128,7 +2128,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_10 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_10], @@ -2136,7 +2136,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_11", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_11], @@ -2144,7 +2144,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_11 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_11], @@ -2152,7 +2152,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_12", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_12], @@ -2160,7 +2160,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_12 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_12], @@ -2168,7 +2168,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_13", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_13], @@ -2176,7 +2176,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_13 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_13], @@ -2184,7 +2184,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_14", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_14], @@ -2192,7 +2192,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_14 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_14], @@ -2200,7 +2200,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_15", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_15], @@ -2208,7 +2208,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_15 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_15], @@ -2216,7 +2216,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_16", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_16], @@ -2224,7 +2224,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_16 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_16], @@ -2232,7 +2232,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_NOP", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOP], @@ -2240,7 +2240,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_NOP long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOP], @@ -2248,7 +2248,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_VER", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_VER], @@ -2256,7 +2256,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_VER long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_VER], @@ -2264,7 +2264,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_IF", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_IF], @@ -2272,7 +2272,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_IF long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_IF], @@ -2280,7 +2280,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_NOTIF", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOTIF], @@ -2288,7 +2288,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_NOTIF long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOTIF], @@ -2296,7 +2296,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_VERIF", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_VERIF], @@ -2304,7 +2304,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_VERIF long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_VERIF], @@ -2312,7 +2312,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_VERNOTIF", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_VERNOTIF], @@ -2320,7 +2320,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_VERNOTIF long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_VERNOTIF], @@ -2328,7 +2328,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_ELSE", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_ELSE], @@ -2336,7 +2336,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_ELSE long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_ELSE], @@ -2344,7 +2344,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_ENDIF", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_ENDIF], @@ -2352,7 +2352,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_ENDIF long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_ENDIF], @@ -2360,7 +2360,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_VERIFY", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_VERIFY], @@ -2368,7 +2368,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_VERIFY long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_VERIFY], @@ -2376,7 +2376,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_RETURN", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_RETURN], @@ -2384,7 +2384,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_RETURN long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_RETURN], @@ -2392,7 +2392,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_TOALTSTACK", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_TOALTSTACK], @@ -2400,7 +2400,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_TOALTSTACK long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_TOALTSTACK], @@ -2408,7 +2408,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_FROMALTSTACK", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_FROMALTSTACK], @@ -2416,7 +2416,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_FROMALTSTACK long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_FROMALTSTACK], @@ -2424,7 +2424,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_2DROP", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_2DROP], @@ -2432,7 +2432,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_2DROP long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_2DROP], @@ -2440,7 +2440,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_2DUP", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_2DUP], @@ -2448,7 +2448,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_2DUP long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_2DUP], @@ -2456,7 +2456,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_3DUP", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_3DUP], @@ -2464,7 +2464,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_3DUP long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_3DUP], @@ -2472,7 +2472,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_2OVER", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_2OVER], @@ -2480,7 +2480,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_2OVER long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_2OVER], @@ -2488,7 +2488,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_2ROT", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_2ROT], @@ -2496,7 +2496,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_2ROT long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_2ROT], @@ -2504,7 +2504,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_2SWAP", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_2SWAP], @@ -2512,7 +2512,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_2SWAP long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_2SWAP], @@ -2520,7 +2520,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_IFDUP", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_IFDUP], @@ -2528,7 +2528,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_IFDUP long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_IFDUP], @@ -2536,7 +2536,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DEPTH", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DEPTH], @@ -2544,7 +2544,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DEPTH long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DEPTH], @@ -2552,7 +2552,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DROP", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DROP], @@ -2560,7 +2560,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DROP long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DROP], @@ -2568,7 +2568,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DUP", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DUP], @@ -2576,7 +2576,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DUP long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DUP], @@ -2584,7 +2584,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_NIP", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NIP], @@ -2592,7 +2592,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_NIP long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NIP], @@ -2600,7 +2600,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_OVER", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_OVER], @@ -2608,7 +2608,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_OVER long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_OVER], @@ -2616,7 +2616,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_PICK", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_PICK], @@ -2624,7 +2624,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_PICK long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_PICK], @@ -2632,7 +2632,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_ROLL", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_ROLL], @@ -2640,7 +2640,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_ROLL long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_ROLL], @@ -2648,7 +2648,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_ROT", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_ROT], @@ -2656,7 +2656,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_ROT long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_ROT], @@ -2664,7 +2664,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_SWAP", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_SWAP], @@ -2672,7 +2672,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_SWAP long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_SWAP], @@ -2680,7 +2680,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_TUCK", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_TUCK], @@ -2688,7 +2688,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_TUCK long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_TUCK], @@ -2696,7 +2696,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_CAT", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_CAT], @@ -2704,7 +2704,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_CAT long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_CAT], @@ -2712,7 +2712,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_SUBSTR", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_SUBSTR], @@ -2720,7 +2720,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_SUBSTR long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_SUBSTR], @@ -2728,7 +2728,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_LEFT", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_LEFT], @@ -2736,7 +2736,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_LEFT long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_LEFT], @@ -2744,7 +2744,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_LEFT", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_LEFT], @@ -2752,7 +2752,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_LEFT long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_LEFT], @@ -2760,7 +2760,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_RIGHT", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_RIGHT], @@ -2768,7 +2768,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_RIGHT long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_RIGHT], @@ -2776,7 +2776,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_SIZE", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_SIZE], @@ -2784,7 +2784,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_SIZE long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_SIZE], @@ -2792,7 +2792,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_INVERT", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_INVERT], @@ -2800,7 +2800,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_INVERT long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_INVERT], @@ -2808,7 +2808,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_AND", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_AND], @@ -2816,7 +2816,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_AND long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_AND], @@ -2824,7 +2824,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_OR", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_OR], @@ -2832,7 +2832,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_OR long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_OR], @@ -2840,7 +2840,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_XOR", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_XOR], @@ -2848,7 +2848,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_XOR long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_XOR], @@ -2856,7 +2856,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_EQUAL", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_EQUAL], @@ -2864,7 +2864,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_EQUAL long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_EQUAL], @@ -2872,7 +2872,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_EQUALVERIFY", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_EQUALVERIFY], @@ -2880,7 +2880,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_EQUALVERIFY long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_EQUALVERIFY], @@ -2888,7 +2888,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_RESERVED1", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_RESERVED1], @@ -2896,7 +2896,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_RESERVED1 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_RESERVED1], @@ -2904,7 +2904,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_RESERVED2", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_RESERVED2], @@ -2912,7 +2912,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_RESERVED2 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_RESERVED2], @@ -2920,7 +2920,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_1ADD", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_1ADD], @@ -2928,7 +2928,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_1ADD long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_1ADD], @@ -2936,7 +2936,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_1SUB", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_1SUB], @@ -2944,7 +2944,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_1SUB long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_1SUB], @@ -2952,7 +2952,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_2MUL", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_2MUL], @@ -2960,7 +2960,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_2MUL long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_2MUL], @@ -2968,7 +2968,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_2DIV", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_2DIV], @@ -2976,7 +2976,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_2DIV long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_2DIV], @@ -2984,7 +2984,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_NEGATE", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NEGATE], @@ -2992,7 +2992,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_NEGATE long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NEGATE], @@ -3000,7 +3000,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_ABS", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_ABS], @@ -3008,7 +3008,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_ABS long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_ABS], @@ -3016,7 +3016,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_NOT", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOT], @@ -3024,7 +3024,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_NOT long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOT], @@ -3032,7 +3032,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_0NOTEQUAL", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_0NOTEQUAL], @@ -3040,7 +3040,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_0NOTEQUAL long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_0NOTEQUAL], @@ -3048,7 +3048,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_ADD", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_ADD], @@ -3056,7 +3056,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_ADD long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_ADD], @@ -3064,7 +3064,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_SUB", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_SUB], @@ -3072,7 +3072,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_SUB long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_SUB], @@ -3080,7 +3080,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_MUL", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_MUL], @@ -3088,7 +3088,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_MUL long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_MUL], @@ -3096,7 +3096,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_DIV", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DIV], @@ -3104,7 +3104,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_DIV long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_DIV], @@ -3112,7 +3112,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_MOD", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_MOD], @@ -3120,7 +3120,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_MOD long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_MOD], @@ -3128,7 +3128,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_LSHIFT", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_LSHIFT], @@ -3136,7 +3136,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_LSHIFT long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_LSHIFT], @@ -3144,7 +3144,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_RSHIFT", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_RSHIFT], @@ -3152,7 +3152,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_RSHIFT long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_RSHIFT], @@ -3160,7 +3160,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_BOOLAND", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_BOOLAND], @@ -3168,7 +3168,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_BOOLAND long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_BOOLAND], @@ -3176,7 +3176,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_BOOLOR", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_BOOLOR], @@ -3184,7 +3184,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_BOOLOR long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_BOOLOR], @@ -3192,7 +3192,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_NUMEQUAL", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NUMEQUAL], @@ -3200,7 +3200,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_NUMEQUAL long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NUMEQUAL], @@ -3208,7 +3208,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_NUMEQUALVERIFY", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NUMEQUALVERIFY], @@ -3216,7 +3216,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_NUMEQUALVERIFY long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NUMEQUALVERIFY], @@ -3224,7 +3224,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_NUMNOTEQUAL", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NUMNOTEQUAL], @@ -3232,7 +3232,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_NUMNOTEQUAL long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NUMNOTEQUAL], @@ -3240,7 +3240,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_LESSTHAN", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_LESSTHAN], @@ -3248,7 +3248,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_LESSTHAN long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_LESSTHAN], @@ -3256,7 +3256,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_GREATERTHAN", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_GREATERTHAN], @@ -3264,7 +3264,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_GREATERTHAN long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_GREATERTHAN], @@ -3272,7 +3272,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_LESSTHANOREQUAL", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_LESSTHANOREQUAL], @@ -3280,7 +3280,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_LESSTHANOREQUAL long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_LESSTHANOREQUAL], @@ -3288,7 +3288,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_GREATERTHANOREQUAL", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_GREATERTHANOREQUAL], @@ -3296,7 +3296,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_GREATERTHANOREQUAL long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_GREATERTHANOREQUAL], @@ -3304,7 +3304,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_MIN", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_MIN], @@ -3312,7 +3312,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_MIN long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_MIN], @@ -3320,7 +3320,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_MAX", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_MAX], @@ -3328,7 +3328,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_MAX long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_MAX], @@ -3336,7 +3336,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_WITHIN", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_WITHIN], @@ -3344,7 +3344,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_WITHIN long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_WITHIN], @@ -3352,7 +3352,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_RIPEMD160", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_RIPEMD160], @@ -3360,7 +3360,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_RIPEMD160 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_RIPEMD160], @@ -3368,7 +3368,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_SHA1", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_SHA1], @@ -3376,7 +3376,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_SHA1 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_SHA1], @@ -3384,7 +3384,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_SHA256", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_SHA256], @@ -3392,7 +3392,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_SHA256 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_SHA256], @@ -3400,7 +3400,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_HASH160", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_HASH160], @@ -3408,7 +3408,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_HASH160 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_HASH160], @@ -3416,7 +3416,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_HASH256", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_HASH256], @@ -3424,7 +3424,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_HASH256 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_HASH256], @@ -3432,7 +3432,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_CODESAPERATOR", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_CODESEPARATOR], @@ -3440,7 +3440,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_CODESEPARATOR long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_CODESEPARATOR], @@ -3448,7 +3448,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_CHECKSIG", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_CHECKSIG], @@ -3456,7 +3456,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_CHECKSIG long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_CHECKSIG], @@ -3464,7 +3464,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_CHECKSIGVERIFY", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_CHECKSIGVERIFY], @@ -3472,7 +3472,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_CHECKSIGVERIFY long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_CHECKSIGVERIFY], @@ -3480,7 +3480,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_CHECKMULTISIG", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_CHECKMULTISIG], @@ -3488,7 +3488,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_CHECKMULTISIG long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_CHECKMULTISIG], @@ -3496,7 +3496,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_CHECKMULTISIGVERIFY", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_CHECKMULTISIGVERIFY], @@ -3504,7 +3504,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_CHECKMULTISIGVERIFY long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_CHECKMULTISIGVERIFY], @@ -3512,7 +3512,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_NOP1", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOP1], @@ -3520,7 +3520,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_NOP1 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOP1], @@ -3528,7 +3528,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_NOP2", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOP2], @@ -3536,7 +3536,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_NOP2 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOP2], @@ -3544,7 +3544,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_NOP3", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOP3], @@ -3552,7 +3552,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_NOP3 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOP3], @@ -3560,7 +3560,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_NOP4", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOP4], @@ -3568,7 +3568,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_NOP4 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOP4], @@ -3576,7 +3576,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_NOP5", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOP5], @@ -3584,7 +3584,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_NOP5 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOP5], @@ -3592,7 +3592,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_NOP6", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOP6], @@ -3600,7 +3600,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_NOP6 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOP6], @@ -3608,7 +3608,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_NOP7", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOP7], @@ -3616,7 +3616,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_NOP7 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOP7], @@ -3624,7 +3624,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_NOP8", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOP8], @@ -3632,7 +3632,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_NOP8 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOP8], @@ -3640,7 +3640,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_NOP9", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOP9], @@ -3648,7 +3648,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_NOP9 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOP9], @@ -3656,7 +3656,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_NOP10", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOP10], @@ -3664,7 +3664,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_NOP10 long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_NOP10], @@ -3672,7 +3672,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_PUBKEYHASH", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_PUBKEYHASH], @@ -3680,7 +3680,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_PUBKEYHASH long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_PUBKEYHASH], @@ -3688,7 +3688,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_PUBKEY", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_PUBKEY], @@ -3696,7 +3696,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_PUBKEY long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_PUBKEY], @@ -3704,7 +3704,7 @@ var popTests = []popTest{ }, expectedErr: StackErrInvalidOpcode, }, - popTest{ + { name: "OP_INVALIDOPCODE", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_INVALIDOPCODE], @@ -3712,7 +3712,7 @@ var popTests = []popTest{ }, expectedErr: nil, }, - popTest{ + { name: "OP_INVALIDOPCODE long", pop: &parsedOpcode{ opcode: opcodemapPreinit[OP_INVALIDOPCODE], diff --git a/opcode_test.go b/opcode_test.go index 3870b6ce..d5591df1 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -483,7 +483,7 @@ func testScript(t *testing.T, script []byte, canonical bool) (err error) { tx := &btcwire.MsgTx{ Version: 1, TxIn: []*btcwire.TxIn{ - &btcwire.TxIn{ + { PreviousOutpoint: btcwire.OutPoint{ Hash: btcwire.ShaHash{}, Index: 0xffffffff, @@ -493,7 +493,7 @@ func testScript(t *testing.T, script []byte, canonical bool) (err error) { }, }, TxOut: []*btcwire.TxOut{ - &btcwire.TxOut{ + { Value: 0x12a05f200, PkScript: []byte{}, }, @@ -4265,7 +4265,7 @@ func testOpcode(t *testing.T, test *detailedTest) { tx := &btcwire.MsgTx{ Version: 1, TxIn: []*btcwire.TxIn{ - &btcwire.TxIn{ + { PreviousOutpoint: btcwire.OutPoint{ Hash: btcwire.ShaHash{}, Index: 0xffffffff, @@ -4275,7 +4275,7 @@ func testOpcode(t *testing.T, test *detailedTest) { }, }, TxOut: []*btcwire.TxOut{ - &btcwire.TxOut{ + { Value: 0x12a05f200, PkScript: []byte{}, }, diff --git a/script.go b/script.go index 2a8a9fcb..3343b2aa 100644 --- a/script.go +++ b/script.go @@ -963,20 +963,20 @@ func getSigOpCount(pops []parsedOpcode, precise bool) int { // output to a 20-byte pubkey hash. func PayToPubKeyHashScript(pubKeyHash []byte) (pkScript []byte, err error) { pops := []parsedOpcode{ - parsedOpcode{ + { opcode: opcodemap[OP_DUP], }, - parsedOpcode{ + { opcode: opcodemap[OP_HASH160], }, - parsedOpcode{ + { opcode: opcodemap[OP_DATA_20], data: pubKeyHash, }, - parsedOpcode{ + { opcode: opcodemap[OP_EQUALVERIFY], }, - parsedOpcode{ + { opcode: opcodemap[OP_CHECKSIG], }, } @@ -987,14 +987,14 @@ func PayToPubKeyHashScript(pubKeyHash []byte) (pkScript []byte, err error) { // script hash. func PayToScriptHashScript(scriptHash []byte) (pkScript []byte, err error) { pops := []parsedOpcode{ - parsedOpcode{ + { opcode: opcodemap[OP_HASH160], }, - parsedOpcode{ + { opcode: opcodemap[OP_DATA_20], data: scriptHash, }, - parsedOpcode{ + { opcode: opcodemap[OP_EQUAL], }, } @@ -1069,7 +1069,7 @@ func signatureScriptCustomReader(reader io.Reader, tx *btcwire.MsgTx, idx int, } } pops := []parsedOpcode{ - parsedOpcode{ + { opcode: opcodemap[byte(len(sig))], data: sig, }, diff --git a/script_test.go b/script_test.go index da17743f..e03743b4 100644 --- a/script_test.go +++ b/script_test.go @@ -33,12 +33,12 @@ type txTest struct { var txTests = []txTest{ // tx 0437cd7f8525ceed2324359c2d0ba26006d92d85. the first tx in the // blockchain that verifies signatures. - txTest{ + { name: "CheckSig", tx: &btcwire.MsgTx{ Version: 1, TxIn: []*btcwire.TxIn{ - &btcwire.TxIn{ + { PreviousOutpoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0xc9, 0x97, 0xa5, 0xe5, @@ -75,7 +75,7 @@ var txTests = []txTest{ }, }, TxOut: []*btcwire.TxOut{ - &btcwire.TxOut{ + { Value: 1000000000, PkScript: []byte{ btcscript.OP_DATA_65, @@ -95,7 +95,7 @@ var txTests = []txTest{ btcscript.OP_CHECKSIG, }, }, - &btcwire.TxOut{ + { Value: 4000000000, PkScript: []byte{ btcscript.OP_DATA_65, @@ -139,12 +139,12 @@ var txTests = []txTest{ }, }, // Previous test with the value of one output changed. - txTest{ + { name: "CheckSig Failure", tx: &btcwire.MsgTx{ Version: 1, TxIn: []*btcwire.TxIn{ - &btcwire.TxIn{ + { PreviousOutpoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0xc9, 0x97, 0xa5, 0xe5, @@ -181,7 +181,7 @@ var txTests = []txTest{ }, }, TxOut: []*btcwire.TxOut{ - &btcwire.TxOut{ + { Value: 1000000000, PkScript: []byte{ btcscript.OP_DATA_65, @@ -201,7 +201,7 @@ var txTests = []txTest{ btcscript.OP_CHECKSIG, }, }, - &btcwire.TxOut{ + { Value: 5000000000, PkScript: []byte{ btcscript.OP_DATA_65, @@ -245,12 +245,12 @@ var txTests = []txTest{ SigOps: 1, }, }, - txTest{ + { name: "CheckSig invalid signature", tx: &btcwire.MsgTx{ Version: 1, TxIn: []*btcwire.TxIn{ - &btcwire.TxIn{ + { PreviousOutpoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0xc9, 0x97, 0xa5, 0xe5, @@ -289,7 +289,7 @@ var txTests = []txTest{ }, }, TxOut: []*btcwire.TxOut{ - &btcwire.TxOut{ + { Value: 1000000000, PkScript: []byte{ btcscript.OP_DATA_65, @@ -309,7 +309,7 @@ var txTests = []txTest{ btcscript.OP_CHECKSIG, }, }, - &btcwire.TxOut{ + { Value: 4000000000, PkScript: []byte{ btcscript.OP_DATA_65, @@ -353,12 +353,12 @@ var txTests = []txTest{ SigOps: 1, }, }, - txTest{ + { name: "CheckSig invalid pubkey", tx: &btcwire.MsgTx{ Version: 1, TxIn: []*btcwire.TxIn{ - &btcwire.TxIn{ + { PreviousOutpoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0xc9, 0x97, 0xa5, 0xe5, @@ -395,7 +395,7 @@ var txTests = []txTest{ }, }, TxOut: []*btcwire.TxOut{ - &btcwire.TxOut{ + { Value: 1000000000, PkScript: []byte{ btcscript.OP_DATA_65, @@ -415,7 +415,7 @@ var txTests = []txTest{ btcscript.OP_CHECKSIG, }, }, - &btcwire.TxOut{ + { Value: 4000000000, PkScript: []byte{ btcscript.OP_DATA_65, @@ -462,12 +462,12 @@ var txTests = []txTest{ }, // tx 599e47a8114fe098103663029548811d2651991b62397e057f0c863c2bc9f9ea // uses checksig with SigHashNone. - txTest{ + { name: "CheckSigHashNone", tx: &btcwire.MsgTx{ Version: 1, TxIn: []*btcwire.TxIn{ - &btcwire.TxIn{ + { PreviousOutpoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x5f, 0x38, 0x6c, 0x8a, @@ -517,7 +517,7 @@ var txTests = []txTest{ }, }, TxOut: []*btcwire.TxOut{ - &btcwire.TxOut{ + { Value: 1000000, PkScript: []byte{ btcscript.OP_DUP, @@ -531,7 +531,7 @@ var txTests = []txTest{ btcscript.OP_CHECKSIG, }, }, - &btcwire.TxOut{ + { Value: 29913632, PkScript: []byte{ btcscript.OP_DUP, @@ -568,12 +568,12 @@ var txTests = []txTest{ SigOps: 1, }, }, - txTest{ + { name: "Non-canonical signature: R value negative", tx: &btcwire.MsgTx{ Version: 1, TxIn: []*btcwire.TxIn{ - &btcwire.TxIn{ + { PreviousOutpoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0xfe, 0x15, 0x62, 0xc4, @@ -621,7 +621,7 @@ var txTests = []txTest{ }, Sequence: 4294967295, }, - &btcwire.TxIn{ + { PreviousOutpoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x2a, 0xc7, 0xee, 0xf8, @@ -671,7 +671,7 @@ var txTests = []txTest{ }, }, TxOut: []*btcwire.TxOut{ - &btcwire.TxOut{ + { Value: 630320000, PkScript: []byte{ btcscript.OP_DUP, @@ -685,7 +685,7 @@ var txTests = []txTest{ btcscript.OP_CHECKSIG, }, }, - &btcwire.TxOut{ + { Value: 100000181, PkScript: []byte{ btcscript.OP_DUP, @@ -699,7 +699,7 @@ var txTests = []txTest{ btcscript.OP_CHECKSIG, }, }, - &btcwire.TxOut{ + { Value: 596516343, PkScript: []byte{ btcscript.OP_DUP, @@ -742,12 +742,12 @@ var txTests = []txTest{ // tx 51bf528ecf3c161e7c021224197dbe84f9a8564212f6207baa014c01a1668e1e // first instance of an AnyoneCanPay signature in the blockchain - txTest{ + { name: "CheckSigHashAnyoneCanPay", tx: &btcwire.MsgTx{ Version: 1, TxIn: []*btcwire.TxIn{ - &btcwire.TxIn{ + { PreviousOutpoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0xf6, 0x04, 0x4c, 0x0a, @@ -789,7 +789,7 @@ var txTests = []txTest{ }, Sequence: 4294967295, }, - &btcwire.TxIn{ + { PreviousOutpoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x9c, 0x6a, 0xf0, 0xdf, @@ -833,7 +833,7 @@ var txTests = []txTest{ }, }, TxOut: []*btcwire.TxOut{ - &btcwire.TxOut{ + { Value: 300000, PkScript: []byte{ btcscript.OP_DUP, @@ -872,12 +872,12 @@ var txTests = []txTest{ }, // tx 6d36bc17e947ce00bb6f12f8e7a56a1585c5a36188ffa2b05e10b4743273a74b // Uses OP_CODESEPARATOR and OP_CHECKMULTISIG - txTest{ + { name: "CheckMultiSig", tx: &btcwire.MsgTx{ Version: 1, TxIn: []*btcwire.TxIn{ - &btcwire.TxIn{ + { PreviousOutpoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x37, 0xb1, 0x7d, 0x76, @@ -915,7 +915,7 @@ var txTests = []txTest{ }, Sequence: 4294967295, }, - &btcwire.TxIn{ + { PreviousOutpoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x37, 0xb1, 0x7d, 0x76, @@ -964,7 +964,7 @@ var txTests = []txTest{ }, }, TxOut: []*btcwire.TxOut{ - &btcwire.TxOut{ + { Value: 4800000, PkScript: []byte{ btcscript.OP_DUP, @@ -995,12 +995,12 @@ var txTests = []txTest{ scriptInfoErr: btcscript.StackErrNonPushOnly, }, // same as previous but with one byte changed to make signature fail - txTest{ + { name: "CheckMultiSig fail", tx: &btcwire.MsgTx{ Version: 1, TxIn: []*btcwire.TxIn{ - &btcwire.TxIn{ + { PreviousOutpoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x37, 0xb1, 0x7d, 0x76, @@ -1038,7 +1038,7 @@ var txTests = []txTest{ }, Sequence: 4294967295, }, - &btcwire.TxIn{ + { PreviousOutpoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x37, 0xb1, 0x7d, 0x76, @@ -1087,7 +1087,7 @@ var txTests = []txTest{ }, }, TxOut: []*btcwire.TxOut{ - &btcwire.TxOut{ + { Value: 5800000, PkScript: []byte{ btcscript.OP_DUP, @@ -1120,12 +1120,12 @@ var txTests = []txTest{ }, // tx e5779b9e78f9650debc2893fd9636d827b26b4ddfa6a8172fe8708c924f5c39d // First P2SH transaction in the blockchain - txTest{ + { name: "P2SH", tx: &btcwire.MsgTx{ Version: 1, TxIn: []*btcwire.TxIn{ - &btcwire.TxIn{ + { PreviousOutpoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x6d, 0x58, 0xf8, 0xa3, @@ -1148,7 +1148,7 @@ var txTests = []txTest{ }, }, TxOut: []*btcwire.TxOut{ - &btcwire.TxOut{ + { Value: 1000000, PkScript: []byte{ btcscript.OP_DUP, @@ -1185,13 +1185,13 @@ var txTests = []txTest{ }, // next few tests are modified versions of previous to hit p2sh error // cases. - txTest{ + { // sigscript changed so that pkscript hash will not match. name: "P2SH - bad hash", tx: &btcwire.MsgTx{ Version: 1, TxIn: []*btcwire.TxIn{ - &btcwire.TxIn{ + { PreviousOutpoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x6d, 0x58, 0xf8, 0xa3, @@ -1214,7 +1214,7 @@ var txTests = []txTest{ }, }, TxOut: []*btcwire.TxOut{ - &btcwire.TxOut{ + { Value: 1000000, PkScript: []byte{ btcscript.OP_DUP, @@ -1250,13 +1250,13 @@ var txTests = []txTest{ SigOps: 0, }, }, - txTest{ + { // sigscript changed so that pkscript hash will not match. name: "P2SH - doesn't parse", tx: &btcwire.MsgTx{ Version: 1, TxIn: []*btcwire.TxIn{ - &btcwire.TxIn{ + { PreviousOutpoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x6d, 0x58, 0xf8, 0xa3, @@ -1279,7 +1279,7 @@ var txTests = []txTest{ }, }, TxOut: []*btcwire.TxOut{ - &btcwire.TxOut{ + { Value: 1000000, PkScript: []byte{ btcscript.OP_DUP, @@ -1309,13 +1309,13 @@ var txTests = []txTest{ bip16: true, scriptInfoErr: btcscript.StackErrShortScript, }, - txTest{ + { // sigscript changed so to be non pushonly. name: "P2SH - non pushonly", tx: &btcwire.MsgTx{ Version: 1, TxIn: []*btcwire.TxIn{ - &btcwire.TxIn{ + { PreviousOutpoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x6d, 0x58, 0xf8, 0xa3, @@ -1342,7 +1342,7 @@ var txTests = []txTest{ }, }, TxOut: []*btcwire.TxOut{ - &btcwire.TxOut{ + { Value: 1000000, PkScript: []byte{ btcscript.OP_DUP, @@ -1373,13 +1373,13 @@ var txTests = []txTest{ nSigOps: 0, // no signature ops in the pushed script. scriptInfoErr: btcscript.StackErrNonPushOnly, }, - txTest{ + { // sigscript changed so to be non pushonly. name: "empty pkScript", tx: &btcwire.MsgTx{ Version: 1, TxIn: []*btcwire.TxIn{ - &btcwire.TxIn{ + { PreviousOutpoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x6d, 0x58, 0xf8, 0xa3, @@ -1402,7 +1402,7 @@ var txTests = []txTest{ }, }, TxOut: []*btcwire.TxOut{ - &btcwire.TxOut{ + { Value: 1000000, PkScript: []byte{ btcscript.OP_DUP, @@ -1509,29 +1509,29 @@ func TestGetPreciseSignOps(t *testing.T) { err error } psocTests := []psocTest{ - psocTest{ + { name: "scriptSig doesn't parse", scriptSig: []byte{btcscript.OP_PUSHDATA1, 2}, err: btcscript.StackErrShortScript, }, - psocTest{ + { name: "scriptSig isn't push only", scriptSig: []byte{btcscript.OP_1, btcscript.OP_DUP}, nSigOps: 0, }, - psocTest{ + { name: "scriptSig length 0", scriptSig: []byte{}, nSigOps: 0, }, - psocTest{ + { name: "No script at the end", // No script at end but still push only. scriptSig: []byte{btcscript.OP_1, btcscript.OP_1}, nSigOps: 0, }, // pushed script doesn't parse. - psocTest{ + { name: "pushed script doesn't parse", scriptSig: []byte{btcscript.OP_DATA_2, btcscript.OP_PUSHDATA1, 2}, @@ -1759,14 +1759,14 @@ type removeOpcodeTest struct { var removeOpcodeTests = []removeOpcodeTest{ // Nothing to remove. - removeOpcodeTest{ + { name: "nothing to remove", before: []byte{btcscript.OP_NOP}, remove: btcscript.OP_CODESEPARATOR, after: []byte{btcscript.OP_NOP}, }, // Test basic opcode removal - removeOpcodeTest{ + { name: "codeseparator 1", before: []byte{btcscript.OP_NOP, btcscript.OP_CODESEPARATOR, btcscript.OP_TRUE}, @@ -1775,7 +1775,7 @@ var removeOpcodeTests = []removeOpcodeTest{ }, // The opcode in question is actually part of the data in a previous // opcode - removeOpcodeTest{ + { name: "codeseparator by coincidence", before: []byte{btcscript.OP_NOP, btcscript.OP_DATA_1, btcscript.OP_CODESEPARATOR, btcscript.OP_TRUE}, @@ -1783,19 +1783,19 @@ var removeOpcodeTests = []removeOpcodeTest{ after: []byte{btcscript.OP_NOP, btcscript.OP_DATA_1, btcscript.OP_CODESEPARATOR, btcscript.OP_TRUE}, }, - removeOpcodeTest{ + { name: "invalid opcode", before: []byte{btcscript.OP_UNKNOWN186}, remove: btcscript.OP_CODESEPARATOR, after: []byte{btcscript.OP_UNKNOWN186}, }, - removeOpcodeTest{ + { name: "invalid length (insruction)", before: []byte{btcscript.OP_PUSHDATA1}, remove: btcscript.OP_CODESEPARATOR, err: btcscript.StackErrShortScript, }, - removeOpcodeTest{ + { name: "invalid length (data)", before: []byte{btcscript.OP_PUSHDATA1, 255, 254}, remove: btcscript.OP_CODESEPARATOR, @@ -1837,73 +1837,73 @@ type removeOpcodeByDataTest struct { } var removeOpcodeByDataTests = []removeOpcodeByDataTest{ - removeOpcodeByDataTest{ + { name: "nothing to do", before: []byte{btcscript.OP_NOP}, remove: []byte{1, 2, 3, 4}, after: []byte{btcscript.OP_NOP}, }, - removeOpcodeByDataTest{ + { name: "simple case", before: []byte{btcscript.OP_DATA_4, 1, 2, 3, 4}, remove: []byte{1, 2, 3, 4}, after: []byte{}, }, - removeOpcodeByDataTest{ + { name: "simple case (miss)", before: []byte{btcscript.OP_DATA_4, 1, 2, 3, 4}, remove: []byte{1, 2, 3, 5}, after: []byte{btcscript.OP_DATA_4, 1, 2, 3, 4}, }, - removeOpcodeByDataTest{ + { name: "simple case (pushdata1)", before: []byte{btcscript.OP_PUSHDATA1, 4, 1, 2, 3, 4}, remove: []byte{1, 2, 3, 4}, after: []byte{}, }, - removeOpcodeByDataTest{ + { name: "simple case (pushdata1 miss)", before: []byte{btcscript.OP_PUSHDATA1, 4, 1, 2, 3, 4}, remove: []byte{1, 2, 3, 5}, after: []byte{btcscript.OP_PUSHDATA1, 4, 1, 2, 3, 4}, }, - removeOpcodeByDataTest{ + { name: "simple case (pushdata2)", before: []byte{btcscript.OP_PUSHDATA2, 4, 0, 1, 2, 3, 4}, remove: []byte{1, 2, 3, 4}, after: []byte{}, }, - removeOpcodeByDataTest{ + { name: "simple case (pushdata2 miss)", before: []byte{btcscript.OP_PUSHDATA2, 4, 0, 1, 2, 3, 4}, remove: []byte{1, 2, 3, 5}, after: []byte{btcscript.OP_PUSHDATA2, 4, 0, 1, 2, 3, 4}, }, - removeOpcodeByDataTest{ + { name: "simple case (pushdata4)", before: []byte{btcscript.OP_PUSHDATA4, 4, 0, 0, 0, 1, 2, 3, 4}, remove: []byte{1, 2, 3, 4}, after: []byte{}, }, - removeOpcodeByDataTest{ + { name: "simple case (pushdata4 miss)", before: []byte{btcscript.OP_PUSHDATA4, 4, 0, 0, 0, 1, 2, 3, 4}, remove: []byte{1, 2, 3, 4, 5}, after: []byte{btcscript.OP_PUSHDATA4, 4, 0, 0, 0, 1, 2, 3, 4}, }, - removeOpcodeByDataTest{ + { name: "invalid opcode ", before: []byte{btcscript.OP_UNKNOWN187}, remove: []byte{1, 2, 3, 4}, after: []byte{btcscript.OP_UNKNOWN187}, }, - removeOpcodeByDataTest{ + { name: "invalid length (instruction)", before: []byte{btcscript.OP_PUSHDATA1}, remove: []byte{1, 2, 3, 4}, err: btcscript.StackErrShortScript, }, - removeOpcodeByDataTest{ + { name: "invalid length (data)", before: []byte{btcscript.OP_PUSHDATA1, 255, 254}, remove: []byte{1, 2, 3, 4}, @@ -1946,7 +1946,7 @@ type scriptTypeTest struct { var scriptTypeTests = []scriptTypeTest{ // tx 0437cd7f8525ceed2324359c2d0ba26006d92d85. - scriptTypeTest{ + { name: "Pay Pubkey", script: []byte{ btcscript.OP_DATA_65, @@ -1963,7 +1963,7 @@ var scriptTypeTests = []scriptTypeTest{ scripttype: btcscript.PubKeyTy, }, // tx 599e47a8114fe098103663029548811d2651991b62397e057f0c863c2bc9f9ea - scriptTypeTest{ + { name: "Pay PubkeyHash", script: []byte{ btcscript.OP_DUP, @@ -1980,7 +1980,7 @@ var scriptTypeTests = []scriptTypeTest{ // part of tx 6d36bc17e947ce00bb6f12f8e7a56a1585c5a36188ffa2b05e10b4743273a74b // codeseparator parts have been elided. (bitcoind's checks for multisig // type doesn't have codesep etc either. - scriptTypeTest{ + { name: "multisig", script: []byte{ btcscript.OP_TRUE, @@ -1996,7 +1996,7 @@ var scriptTypeTests = []scriptTypeTest{ }, // tx e5779b9e78f9650debc2893fd9636d827b26b4ddfa6a8172fe8708c924f5c39d // P2SH - scriptTypeTest{ + { name: "P2SH", script: []byte{ btcscript.OP_HASH160, @@ -2009,7 +2009,7 @@ var scriptTypeTests = []scriptTypeTest{ scripttype: btcscript.ScriptHashTy, }, // Nulldata with no data at all. - scriptTypeTest{ + { name: "nulldata", script: []byte{ btcscript.OP_RETURN, @@ -2017,7 +2017,7 @@ var scriptTypeTests = []scriptTypeTest{ scripttype: btcscript.NullDataTy, }, // Nulldata with small data. - scriptTypeTest{ + { name: "nulldata2", script: []byte{ btcscript.OP_RETURN, @@ -2027,7 +2027,7 @@ var scriptTypeTests = []scriptTypeTest{ scripttype: btcscript.NullDataTy, }, // Nulldata with max allowed data. - scriptTypeTest{ + { name: "nulldata3", script: []byte{ btcscript.OP_RETURN, @@ -2047,7 +2047,7 @@ var scriptTypeTests = []scriptTypeTest{ scripttype: btcscript.NullDataTy, }, // Nulldata with more than max allowed data (so therefore nonstandard) - scriptTypeTest{ + { name: "nulldata4", script: []byte{ btcscript.OP_RETURN, @@ -2069,7 +2069,7 @@ var scriptTypeTests = []scriptTypeTest{ }, // Almost nulldata, but add an additional opcode after the data to make // it nonstandard. - scriptTypeTest{ + { name: "nulldata5", script: []byte{ btcscript.OP_RETURN, @@ -2080,7 +2080,7 @@ var scriptTypeTests = []scriptTypeTest{ scripttype: btcscript.NonStandardTy, }, // The next few are almost multisig (it is the more complex script type) // but with various changes to make it fail. - scriptTypeTest{ + { // multisig but funny nsigs.. name: "strange 1", script: []byte{ @@ -2095,7 +2095,7 @@ var scriptTypeTests = []scriptTypeTest{ }, scripttype: btcscript.NonStandardTy, }, - scriptTypeTest{ + { name: "strange 2", // multisig but funny pubkey. script: []byte{ @@ -2106,7 +2106,7 @@ var scriptTypeTests = []scriptTypeTest{ }, scripttype: btcscript.NonStandardTy, }, - scriptTypeTest{ + { name: "strange 3", // multisig but no matching npubkeys opcode. script: []byte{ @@ -2126,7 +2126,7 @@ var scriptTypeTests = []scriptTypeTest{ }, scripttype: btcscript.NonStandardTy, }, - scriptTypeTest{ + { name: "strange 4", // multisig but with multisigverify script: []byte{ @@ -2141,7 +2141,7 @@ var scriptTypeTests = []scriptTypeTest{ }, scripttype: btcscript.NonStandardTy, }, - scriptTypeTest{ + { name: "strange 5", // multisig but wrong length. script: []byte{ @@ -2150,7 +2150,7 @@ var scriptTypeTests = []scriptTypeTest{ }, scripttype: btcscript.NonStandardTy, }, - scriptTypeTest{ + { name: "doesn't parse", script: []byte{ btcscript.OP_DATA_5, 0x1, 0x2, 0x3, 0x4, @@ -2191,11 +2191,11 @@ func TestBadPC(t *testing.T) { script, off int } pcTests := []pcTest{ - pcTest{ + { script: 2, off: 0, }, - pcTest{ + { script: 0, off: 2, }, @@ -2204,7 +2204,7 @@ func TestBadPC(t *testing.T) { tx := &btcwire.MsgTx{ Version: 1, TxIn: []*btcwire.TxIn{ - &btcwire.TxIn{ + { PreviousOutpoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0xc9, 0x97, 0xa5, 0xe5, @@ -2223,7 +2223,7 @@ func TestBadPC(t *testing.T) { }, }, TxOut: []*btcwire.TxOut{ - &btcwire.TxOut{ + { Value: 1000000000, PkScript: []byte{}, }, @@ -2263,7 +2263,7 @@ func TestCheckErrorCondition(t *testing.T) { tx := &btcwire.MsgTx{ Version: 1, TxIn: []*btcwire.TxIn{ - &btcwire.TxIn{ + { PreviousOutpoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0xc9, 0x97, 0xa5, 0xe5, @@ -2282,7 +2282,7 @@ func TestCheckErrorCondition(t *testing.T) { }, }, TxOut: []*btcwire.TxOut{ - &btcwire.TxOut{ + { Value: 1000000000, PkScript: []byte{}, }, @@ -2423,10 +2423,10 @@ const coinbaseVal = 2500000000 const fee = 5000000 var SigScriptTests = []TstSigScript{ - TstSigScript{ + { name: "one input uncompressed", inputs: []TstInput{ - TstInput{ + { txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), sigscriptGenerates: true, inputValidates: true, @@ -2437,16 +2437,16 @@ var SigScriptTests = []TstSigScript{ compress: false, scriptAtWrongIndex: false, }, - TstSigScript{ + { name: "two inputs uncompressed", inputs: []TstInput{ - TstInput{ + { txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), sigscriptGenerates: true, inputValidates: true, indexOutOfRange: false, }, - TstInput{ + { txout: btcwire.NewTxOut(coinbaseVal+fee, uncompressedPkScript), sigscriptGenerates: true, inputValidates: true, @@ -2457,10 +2457,10 @@ var SigScriptTests = []TstSigScript{ compress: false, scriptAtWrongIndex: false, }, - TstSigScript{ + { name: "one input compressed", inputs: []TstInput{ - TstInput{ + { txout: btcwire.NewTxOut(coinbaseVal, compressedPkScript), sigscriptGenerates: true, inputValidates: true, @@ -2471,16 +2471,16 @@ var SigScriptTests = []TstSigScript{ compress: true, scriptAtWrongIndex: false, }, - TstSigScript{ + { name: "two inputs compressed", inputs: []TstInput{ - TstInput{ + { txout: btcwire.NewTxOut(coinbaseVal, compressedPkScript), sigscriptGenerates: true, inputValidates: true, indexOutOfRange: false, }, - TstInput{ + { txout: btcwire.NewTxOut(coinbaseVal+fee, compressedPkScript), sigscriptGenerates: true, inputValidates: true, @@ -2491,10 +2491,10 @@ var SigScriptTests = []TstSigScript{ compress: true, scriptAtWrongIndex: false, }, - TstSigScript{ + { name: "hashtype SigHashNone", inputs: []TstInput{ - TstInput{ + { txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), sigscriptGenerates: true, inputValidates: true, @@ -2505,10 +2505,10 @@ var SigScriptTests = []TstSigScript{ compress: false, scriptAtWrongIndex: false, }, - TstSigScript{ + { name: "hashtype SigHashSingle", inputs: []TstInput{ - TstInput{ + { txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), sigscriptGenerates: true, inputValidates: true, @@ -2519,10 +2519,10 @@ var SigScriptTests = []TstSigScript{ compress: false, scriptAtWrongIndex: false, }, - TstSigScript{ + { name: "hashtype SigHashAnyoneCanPay", inputs: []TstInput{ - TstInput{ + { txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), sigscriptGenerates: true, inputValidates: true, @@ -2533,10 +2533,10 @@ var SigScriptTests = []TstSigScript{ compress: false, scriptAtWrongIndex: false, }, - TstSigScript{ + { name: "hashtype non-standard", inputs: []TstInput{ - TstInput{ + { txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), sigscriptGenerates: true, inputValidates: true, @@ -2547,10 +2547,10 @@ var SigScriptTests = []TstSigScript{ compress: false, scriptAtWrongIndex: false, }, - TstSigScript{ + { name: "invalid compression", inputs: []TstInput{ - TstInput{ + { txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), sigscriptGenerates: true, inputValidates: false, @@ -2561,10 +2561,10 @@ var SigScriptTests = []TstSigScript{ compress: true, scriptAtWrongIndex: false, }, - TstSigScript{ + { name: "short PkScript", inputs: []TstInput{ - TstInput{ + { txout: btcwire.NewTxOut(coinbaseVal, shortPkScript), sigscriptGenerates: false, indexOutOfRange: false, @@ -2574,16 +2574,16 @@ var SigScriptTests = []TstSigScript{ compress: false, scriptAtWrongIndex: false, }, - TstSigScript{ + { name: "valid script at wrong index", inputs: []TstInput{ - TstInput{ + { txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), sigscriptGenerates: true, inputValidates: true, indexOutOfRange: false, }, - TstInput{ + { txout: btcwire.NewTxOut(coinbaseVal+fee, uncompressedPkScript), sigscriptGenerates: true, inputValidates: true, @@ -2594,16 +2594,16 @@ var SigScriptTests = []TstSigScript{ compress: false, scriptAtWrongIndex: true, }, - TstSigScript{ + { name: "index out of range", inputs: []TstInput{ - TstInput{ + { txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), sigscriptGenerates: true, inputValidates: true, indexOutOfRange: false, }, - TstInput{ + { txout: btcwire.NewTxOut(coinbaseVal+fee, uncompressedPkScript), sigscriptGenerates: true, inputValidates: true, @@ -2614,10 +2614,10 @@ var SigScriptTests = []TstSigScript{ compress: false, scriptAtWrongIndex: true, }, - TstSigScript{ + { name: "invalid reader", inputs: []TstInput{ - TstInput{ + { txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), invalidReader: true, sigscriptGenerates: false, From fcd73f75ea43b79e68eba9c0b111d01dc98e84b4 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 19 Feb 2014 13:22:33 -0600 Subject: [PATCH 089/174] Correct log trace for failed script execution. The function needs to be wrapped by a newLogClosure for the logger to be able to log it. --- script.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/script.go b/script.go index 3343b2aa..3072741c 100644 --- a/script.go +++ b/script.go @@ -528,12 +528,12 @@ func (s *Script) CheckErrorCondition() (err error) { v, err := s.dstack.PopBool() if err == nil && v == false { // log interesting data. - log.Tracef("%v", func() string { + log.Tracef("%v", newLogClosure(func() string { dis0, _ := s.DisasmScript(0) dis1, _ := s.DisasmScript(1) return fmt.Sprintf("scripts failed: script0: %s\n"+ "script1: %s", dis0, dis1) - }) + })) err = StackErrScriptFailed } if err == nil && len(s.condStack) != 1 { From 1d360509f45df050a4acec531a4b2dfe2158fb2d Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 19 Feb 2014 14:29:43 -0600 Subject: [PATCH 090/174] Correct handling for multi-sig zero signatures. It is possible for a multisignature transaction to require zero signatures. For example, input 2 of testnet transaction b2d93dfd0b2c1a380e55e76a8d9cb3075dec9f4474e9485be008c337fd62c1f7 in block number 185117. Previously the code was pushing a false to the stack when no valid signatures were found. This commit remedies that by pushing true when no valid signatures were found, but none are required. Otherwise it still pushes false when no valid signatures were found, but some are required. Fixes #7. ok @owainga --- opcode.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opcode.go b/opcode.go index bee36f85..710cd212 100644 --- a/opcode.go +++ b/opcode.go @@ -1831,7 +1831,7 @@ func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error { } if len(signatures) == 0 { - s.dstack.PushBool(false) + s.dstack.PushBool(nsig == 0) return nil } From 37a45ec68371bb98d7f2f7f28c6175669886cb56 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 19 Feb 2014 16:17:02 -0600 Subject: [PATCH 091/174] Allow multi-sig scripts with zero signatures. This commit builds off the previous commit which fixed the execution of multi-signature scripts with zero required signatures. It introduces the concept of a "small int" which is one of OP_0 or OP_1 - OP_16. All areas of code that deal with multi-sig transactions now make use of these to ensure consistent handling. This fixes a few issues surrounding multi-sig zero required signature transactions included proper detection as a multi-sig script, signature counting for script statistics, and ok @owainga --- address.go | 4 ++-- script.go | 39 ++++++++++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/address.go b/address.go index db4b274d..f0f0eae0 100644 --- a/address.go +++ b/address.go @@ -65,8 +65,8 @@ func ExtractPkScriptAddrs(pkScript []byte, net btcwire.BitcoinNet) (ScriptClass, // Therefore the number of required signatures is the 1st item // on the stack and the number of public keys is the 2nd to last // item on the stack. - requiredSigs = int(pops[0].opcode.value - (OP_1 - 1)) - numPubKeys := int(pops[len(pops)-2].opcode.value - (OP_1 - 1)) + requiredSigs = asSmallInt(pops[0].opcode) + numPubKeys := asSmallInt(pops[len(pops)-2].opcode) // Extract the public keys while skipping any that are invalid. addrs = make([]btcutil.Address, 0, numPubKeys) diff --git a/script.go b/script.go index 3072741c..16acdb9b 100644 --- a/script.go +++ b/script.go @@ -192,6 +192,15 @@ type Script struct { savedFirstStack [][]byte // stack from first script for bip16 scripts } +// isSmallInt returns whether or not the opcode is considered a small integer, +// which is an OP_0, or OP_1 through OP_16. +func isSmallInt(op *opcode) bool { + if op.value == OP_0 || (op.value >= OP_1 && op.value <= OP_16) { + return true + } + return false +} + // isPubkey returns true if the script passed is a pubkey transaction, false // otherwise. func isPubkey(pops []parsedOpcode) bool { @@ -237,16 +246,14 @@ func IsPayToScriptHash(script []byte) bool { func isMultiSig(pops []parsedOpcode) bool { l := len(pops) // absolute minimum is 1 pubkey so - // OP_1-16, pubkey, OP_1, OP_CHECKMULTISIG + // OP_0/OP_1-16, pubkey, OP_1, OP_CHECKMULTISIG if l < 4 { return false } - if pops[0].opcode.value < OP_1 || - pops[0].opcode.value > OP_16 { + if !isSmallInt(pops[0].opcode) { return false } - if pops[l-2].opcode.value < OP_1 || - pops[l-2].opcode.value > OP_16 { + if !isSmallInt(pops[l-2].opcode) { return false } if pops[l-1].opcode.value != OP_CHECKMULTISIG { @@ -1096,10 +1103,10 @@ func expectedInputs(pops []parsedOpcode, class ScriptClass) int { case MultiSigTy: // Standard multisig has a push a small number for the number // of sigs and number of keys. - // Check the first push instrution to see how many arguments are - // expected. typoeOfScript already checked this so that we know - // it'll be one of OP_1 - OP_16. - return int(pops[0].opcode.value - (OP_1 - 1)) + // Check the first push instruction to see how many arguments + // are expected. typeOfScript already checked this so we know + // it'll be a small int. + return asSmallInt(pops[0].opcode) case NullDataTy: fallthrough default: @@ -1176,6 +1183,16 @@ func CalcScriptInfo(sigscript, pkscript []byte, bip16 bool) (*ScriptInfo, error) return si, nil } +// asSmallInt returns the passed opcode, which must be true according to +// isSmallInt(), as an integer. +func asSmallInt(op *opcode) int { + if op.value == OP_0 { + return 0 + } + + return int(op.value - (OP_1 - 1)) +} + // CalcMultiSigStats returns the number of public keys and signatures from // a multi-signature transaction script. The passed script MUST already be // known to be a multi-signature script. @@ -1196,7 +1213,7 @@ func CalcMultiSigStats(script []byte) (int, int, error) { return 0, 0, StackErrUnderflow } - numSigs := int(pops[0].opcode.value - (OP_1 - 1)) - numPubKeys := int(pops[len(pops)-2].opcode.value - (OP_1 - 1)) + numSigs := asSmallInt(pops[0].opcode) + numPubKeys := asSmallInt(pops[len(pops)-2].opcode) return numPubKeys, numSigs, nil } From a6cdb8b84452dfb0ae3f0951a529a45e9b78be77 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 19 Feb 2014 16:52:11 -0600 Subject: [PATCH 092/174] Add tests for multisig with zero required sigs. --- script_test.go | 61 +++++++++++++++++++++ test_coverage.txt | 132 +++++++++++++++++++++++----------------------- 2 files changed, 128 insertions(+), 65 deletions(-) diff --git a/script_test.go b/script_test.go index e03743b4..14061dd5 100644 --- a/script_test.go +++ b/script_test.go @@ -1118,6 +1118,67 @@ var txTests = []txTest{ nSigOps: 0, // multisig is in the pkScript! scriptInfoErr: btcscript.StackErrNonPushOnly, }, + // taken from tx b2d93dfd0b2c1a380e55e76a8d9cb3075dec9f4474e9485be008c337fd62c1f7 + // on testnet + // multisig with zero required signatures + { + name: "CheckMultiSig zero required signatures", + tx: &btcwire.MsgTx{ + Version: 1, + TxIn: []*btcwire.TxIn{ + { + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash([32]byte{ + 0x37, 0xb1, 0x7d, 0x76, + 0x38, 0x51, 0xcd, 0x1a, + 0xb0, 0x4a, 0x42, 0x44, + 0x63, 0xd4, 0x13, 0xc4, + 0xee, 0x5c, 0xf6, 0x13, + 0x04, 0xc7, 0xfd, 0x76, + 0x97, 0x7b, 0xea, 0x7f, + 0xce, 0x07, 0x57, 0x05, + }), + Index: 0, + }, + SignatureScript: []byte{ + btcscript.OP_0, + btcscript.OP_DATA_37, + btcscript.OP_0, + btcscript.OP_DATA_33, + 0x02, 0x4a, 0xb3, 0x3c, 0x3a, + 0x54, 0x7a, 0x37, 0x29, 0x3e, + 0xb8, 0x75, 0xb4, 0xbb, 0xdb, + 0xd4, 0x73, 0xe9, 0xd4, 0xba, + 0xfd, 0xf3, 0x56, 0x87, 0xe7, + 0x97, 0x44, 0xdc, 0xd7, 0x0f, + 0x6e, 0x4d, 0xe2, + btcscript.OP_1, + btcscript.OP_CHECKMULTISIG, + }, + Sequence: 4294967295, + }, + }, + TxOut: []*btcwire.TxOut{}, + LockTime: 0, + }, + pkScript: []byte{ + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0x2c, 0x6b, 0x10, 0x7f, 0xdf, 0x10, 0x6f, 0x22, 0x6f, + 0x3f, 0xa3, 0x27, 0xba, 0x36, 0xd6, 0xe3, 0xca, 0xc7, + 0x3d, 0xf0, + btcscript.OP_EQUAL, + }, + idx: 0, + bip16: true, + nSigOps: 1, + scriptInfo: btcscript.ScriptInfo{ + PkScriptClass: btcscript.ScriptHashTy, + NumInputs: 2, + ExpectedInputs: 1, + SigOps: 1, + }, + }, // tx e5779b9e78f9650debc2893fd9636d827b26b4ddfa6a8172fe8708c924f5c39d // First P2SH transaction in the blockchain { diff --git a/test_coverage.txt b/test_coverage.txt index a115226d..3fa16760 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -1,146 +1,148 @@ +github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 100.00% (62/62) github.com/conformal/btcscript/script.go Script.Step 100.00% (37/37) github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (30/30) github.com/conformal/btcscript/address.go ExtractPkScriptAddrs 100.00% (27/27) github.com/conformal/btcscript/script.go CalcScriptInfo 100.00% (25/25) github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23) -github.com/conformal/btcscript/stack.go asInt 100.00% (21/21) github.com/conformal/btcscript/script.go NewScript 100.00% (21/21) -github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (16/16) +github.com/conformal/btcscript/stack.go asInt 100.00% (21/21) github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (16/16) +github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (16/16) github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (14/14) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) -github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) -github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) +github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) +github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) -github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) -github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) -github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) +github.com/conformal/btcscript/script.go PayToAddrScript 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) -github.com/conformal/btcscript/script.go PayToAddrScript 100.00% (8/8) +github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) +github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) github.com/conformal/btcscript/script.go unparseScript 100.00% (7/7) -github.com/conformal/btcscript/script.go typeOfScript 100.00% (7/7) -github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) +github.com/conformal/btcscript/script.go typeOfScript 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) -github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (4/4) -github.com/conformal/btcscript/script.go getStack 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) -github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) -github.com/conformal/btcscript/script.go isNullData 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (4/4) +github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) +github.com/conformal/btcscript/script.go getStack 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) +github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) +github.com/conformal/btcscript/script.go isNullData 100.00% (4/4) +github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) +github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) github.com/conformal/btcscript/script.go ScriptClass.String 100.00% (3/3) github.com/conformal/btcscript/script.go setStack 100.00% (3/3) -github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) -github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) +github.com/conformal/btcscript/script.go isSmallInt 100.00% (3/3) +github.com/conformal/btcscript/script.go asSmallInt 100.00% (3/3) +github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) github.com/conformal/btcscript/script.go PayToPubKeyHashScript 100.00% (2/2) github.com/conformal/btcscript/script.go PayToScriptHashScript 100.00% (2/2) +github.com/conformal/btcscript/log.go init 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) github.com/conformal/btcscript/opcode.go init 100.00% (1/1) -github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) -github.com/conformal/btcscript/log.go init 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) +github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.28% (57/58) -github.com/conformal/btcscript/opcode.go opcodeCheckSig 90.62% (29/32) +github.com/conformal/btcscript/opcode.go opcodeCheckSig 90.00% (27/30) github.com/conformal/btcscript/script.go expectedInputs 85.71% (6/7) github.com/conformal/btcscript/script.go calcScriptHash 82.05% (32/39) github.com/conformal/btcscript/script.go Script.CheckErrorCondition 78.57% (11/14) @@ -149,7 +151,7 @@ github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/10) github.com/conformal/btcscript/script.go CalcMultiSigStats 0.00% (0/8) github.com/conformal/btcscript/script.go IsPushOnlyScript 0.00% (0/4) -github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) github.com/conformal/btcscript/log.go UseLogger 0.00% (0/1) -github.com/conformal/btcscript --------------------------- 95.08% (967/1017) +github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) +github.com/conformal/btcscript --------------------------- 95.22% (976/1025) From b8dc1b66e5d37da87fc32868e66a784fa845ed4b Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 19 Feb 2014 20:58:21 -0600 Subject: [PATCH 093/174] Add new ScriptBuilder for building custom scripts. This commit adds a new ScriptBuilder interface that can be used to build custom scripts. It currently is fairly basic, but it allows you to push raw opcodes, ints, and data while respecting canonical encoding. These primitives are sufficient to build any script. This could be improved upon with quite a few things. One example would be functions for certain opcodes that take properly typed parameters to make it harder to create invalid scripts. For now though, it is already quite useful since it handles all of the opcode selection for canonical data pushes and integer encoding. The initial discussion took place in #5. --- scriptbuilder.go | 131 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 scriptbuilder.go diff --git a/scriptbuilder.go b/scriptbuilder.go new file mode 100644 index 00000000..a029849b --- /dev/null +++ b/scriptbuilder.go @@ -0,0 +1,131 @@ +// Copyright (c) 2013-2014 Conformal Systems LLC. +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcscript + +import ( + "encoding/binary" + "math/big" +) + +const ( + // defaultScriptAlloc is the default size used for the backing array + // for a script being built by the ScriptBuilder. The array will + // dynamically grow as needed, but this figure is intended to provide + // enough space for vast majority of scripts without needing to grow the + // backing array multiple times. + defaultScriptAlloc = 500 +) + +// ScriptBuilder provides a facility for building custom scripts. It allows +// you to push opcodes, ints, and, data while respecting canonical encoding. It +// does not ensure the script will execute correctly. +// +// For example, the following would build a 2-of-3 multisig script for usage in +// a pay-to-script-hash: +// builder := btcscript.NewScriptBuilder() +// builder.PushOp(btcscript.OP_2).PushData(pubKey1).PushData(pubKey2) +// builder.PushData(pubKey3).PushOp(btcscript.OP_3) +// builder.PushOp(btcscript.OP_CHECKMULTISIG) +// fmt.Printf("Final multi-sig script: %x\n", builder.Script()) +type ScriptBuilder struct { + script []byte +} + +// PushOp pushes the passed opcode to the end of the script. +func (b *ScriptBuilder) PushOp(opcode byte) *ScriptBuilder { + b.script = append(b.script, opcode) + return b +} + +// PushData pushes the passed data to the end of the script. It automatically +// chooses canonical opcodes depending on the length of the data. +func (b *ScriptBuilder) PushData(data []byte) *ScriptBuilder { + // Don't modify the script at all if no data was passed. + dataLen := len(data) + if dataLen == 0 { + return b + } + + // When the data consists of a single number that can be represented + // by one of the "small integer" opcodes, use that opcode instead of + // a data push opcode followed by the number. + if dataLen == 1 && data[0] == 0 { + b.script = append(b.script, OP_0) + return b + } else if dataLen == 1 && data[0] <= 16 { + b.script = append(b.script, byte((OP_1-1)+data[0])) + return b + } + + // Use one of the OP_DATA_# opcodes if the length of the data is small + // enough so the data push instruction is only a single byte. + // Otherwise, choose the smallest possible OP_PUSHDATA# opcode that + // can represent the length of the data. + if dataLen < OP_PUSHDATA1 { + b.script = append(b.script, byte((OP_DATA_1-1)+dataLen)) + } else if dataLen <= 0xff { + b.script = append(b.script, OP_PUSHDATA1, byte(dataLen)) + } else if dataLen <= 0xffff { + buf := make([]byte, 2) + binary.LittleEndian.PutUint16(buf, uint16(dataLen)) + b.script = append(b.script, OP_PUSHDATA2) + b.script = append(b.script, buf...) + } else { + buf := make([]byte, 4) + binary.LittleEndian.PutUint32(buf, uint32(dataLen)) + b.script = append(b.script, OP_PUSHDATA4) + b.script = append(b.script, buf...) + } + + // Append the actual data. + b.script = append(b.script, data...) + + return b +} + +// PushInt64 pushes the passed integer to the end of the script. +func (b *ScriptBuilder) PushInt64(val int64) *ScriptBuilder { + // Fast path for small integers and OP_1NEGATE. + if val == -1 || (val >= 1 && val <= 16) { + b.script = append(b.script, byte((OP_1-1)+val)) + return b + } + + return b.PushData(fromInt(new(big.Int).SetInt64(val))) +} + +// PushUint64 pushes the passed integer to the end of the script. +func (b *ScriptBuilder) PushUint64(val uint64) *ScriptBuilder { + // Fast path for small integers. + if val == 0 { + b.script = append(b.script, OP_0) + return b + } + if val >= 1 && val <= 16 { + b.script = append(b.script, byte((OP_1-1)+val)) + return b + } + + return b.PushData(fromInt(new(big.Int).SetUint64(val))) +} + +// Reset resets the script so it has no content. +func (b *ScriptBuilder) Reset() *ScriptBuilder { + b.script = b.script[0:0] + return b +} + +// Script returns the currently built script. +func (b *ScriptBuilder) Script() []byte { + return b.script +} + +// NewScriptBuilder returns a new instance of a script builder. See +// ScriptBuilder for details. +func NewScriptBuilder() *ScriptBuilder { + return &ScriptBuilder{ + script: make([]byte, 0, defaultScriptAlloc), + } +} From 61d270957e5bc13934a17f2d7b4daee93d4f9bad Mon Sep 17 00:00:00 2001 From: David Hill Date: Thu, 20 Feb 2014 00:05:35 -0500 Subject: [PATCH 094/174] Add HasCanonicalPushes Closes #6. ok @davecgh --- script.go | 35 +++++++++++++++++++++++++++++++++++ script_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/script.go b/script.go index 16acdb9b..bd3b90cb 100644 --- a/script.go +++ b/script.go @@ -308,6 +308,41 @@ func IsPushOnlyScript(script []byte) bool { return isPushOnly(pops) } +// HasCanonicalPushes returns whether or not the passed script only contains +// canonical data pushes. A canonical data push one where the fewest number of +// bytes possible to encode the size of the data being pushed is used. This +// includes using the small integer opcodes for single byte data that can be +// represented directly. +func HasCanonicalPushes(script []byte) bool { + pops, err := parseScript(script) + if err != nil { + return false + } + + for _, pop := range pops { + opcode := pop.opcode.value + data := pop.data + dataLen := len(pop.data) + if opcode > OP_16 { + continue + } + if opcode < OP_PUSHDATA1 && opcode > OP_0 && (dataLen == 1 && data[0] <= 16) { + return false + } + if opcode == OP_PUSHDATA1 && dataLen < OP_PUSHDATA1 { + return false + } + if opcode == OP_PUSHDATA2 && dataLen <= 0xff { + return false + } + if opcode == OP_PUSHDATA4 && dataLen <= 0xffff { + return false + } + } + + return true +} + // GetScriptClass returns the class of the script passed. If the script does not // parse then NonStandardTy will be returned. func GetScriptClass(script []byte) ScriptClass { diff --git a/script_test.go b/script_test.go index 14061dd5..3f193016 100644 --- a/script_test.go +++ b/script_test.go @@ -15,6 +15,31 @@ import ( "testing" ) +func TestStandardPushes(t *testing.T) { + for i := 0; i < 1000; i++ { + builder := btcscript.NewScriptBuilder() + builder.PushInt64(int64(i)) + if result := btcscript.IsPushOnlyScript(builder.Script()); !result { + t.Errorf("StandardPushesTests IsPushOnlyScript test #%d failed: %x\n", i, builder.Script()) + } + if result := btcscript.HasCanonicalPushes(builder.Script()); !result { + t.Errorf("StandardPushesTests HasCanonicalPushes test #%d failed: %x\n", i, builder.Script()) + continue + } + } + for i := 0; i < 1000; i++ { + builder := btcscript.NewScriptBuilder() + builder.PushData(bytes.Repeat([]byte{0x49}, i)) + if result := btcscript.IsPushOnlyScript(builder.Script()); !result { + t.Errorf("StandardPushesTests IsPushOnlyScript test #%d failed: %x\n", i, builder.Script()) + } + if result := btcscript.HasCanonicalPushes(builder.Script()); !result { + t.Errorf("StandardPushesTests HasCanonicalPushes test #%d failed: %x\n", i, builder.Script()) + continue + } + } +} + type txTest struct { name string tx *btcwire.MsgTx From 50173b865bd352e1dd9c6308027127c750076196 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 20 Feb 2014 01:46:56 -0600 Subject: [PATCH 095/174] Allow push of 0 via new ScriptBuilder PushInt64. Nothing was being pushed for 0 to the new ScriptBuilder due to the fact Go big integers when set to 0 have no bytes. --- scriptbuilder.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scriptbuilder.go b/scriptbuilder.go index a029849b..d7980621 100644 --- a/scriptbuilder.go +++ b/scriptbuilder.go @@ -88,6 +88,10 @@ func (b *ScriptBuilder) PushData(data []byte) *ScriptBuilder { // PushInt64 pushes the passed integer to the end of the script. func (b *ScriptBuilder) PushInt64(val int64) *ScriptBuilder { // Fast path for small integers and OP_1NEGATE. + if val == 0 { + b.script = append(b.script, OP_0) + return b + } if val == -1 || (val >= 1 && val <= 16) { b.script = append(b.script, byte((OP_1-1)+val)) return b From 5a660e95f9ae9c0fd39a229783e733baa7558b82 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 20 Feb 2014 02:47:52 -0600 Subject: [PATCH 096/174] Add 100% test coverage for new ScriptBuilder code. --- scriptbuilder_test.go | 249 ++++++++++++++++++++++++++++++++++++++++++ test_coverage.txt | 184 ++++++++++++++++--------------- 2 files changed, 345 insertions(+), 88 deletions(-) create mode 100644 scriptbuilder_test.go diff --git a/scriptbuilder_test.go b/scriptbuilder_test.go new file mode 100644 index 00000000..08b3398c --- /dev/null +++ b/scriptbuilder_test.go @@ -0,0 +1,249 @@ +// Copyright (c) 2013-2014 Conformal Systems LLC. +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcscript_test + +import ( + "bytes" + "github.com/conformal/btcscript" + "testing" +) + +// TestScriptBuilderPushOp tests that pushing opcodes to a script via the +// ScriptBuilder API works as expected. +func TestScriptBuilderPushOp(t *testing.T) { + tests := []struct { + name string + opcodes []byte + expected []byte + }{ + { + name: "push OP_0", + opcodes: []byte{btcscript.OP_0}, + expected: []byte{btcscript.OP_0}, + }, + { + name: "push OP_1 OP_2", + opcodes: []byte{btcscript.OP_1, btcscript.OP_2}, + expected: []byte{btcscript.OP_1, btcscript.OP_2}, + }, + { + name: "push OP_HASH160 OP_EQUAL", + opcodes: []byte{btcscript.OP_HASH160, btcscript.OP_EQUAL}, + expected: []byte{btcscript.OP_HASH160, btcscript.OP_EQUAL}, + }, + } + + builder := btcscript.NewScriptBuilder() + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + builder.Reset() + for _, opcode := range test.opcodes { + builder.PushOp(opcode) + } + result := builder.Script() + if !bytes.Equal(result, test.expected) { + t.Errorf("ScriptBuilder.PushOp #%d (%s) wrong result\n"+ + "got: %x\nwant: %x", i, test.name, result, + test.expected) + continue + } + } +} + +// TestScriptBuilderPushInt64 tests that pushing signed integers to a script via +// the ScriptBuilder API works as expected. +func TestScriptBuilderPushInt64(t *testing.T) { + tests := []struct { + name string + val int64 + expected []byte + }{ + {name: "push -1", val: -1, expected: []byte{btcscript.OP_1NEGATE}}, + {name: "push small int 0", val: 0, expected: []byte{btcscript.OP_0}}, + {name: "push small int 1", val: 1, expected: []byte{btcscript.OP_1}}, + {name: "push small int 2", val: 2, expected: []byte{btcscript.OP_2}}, + {name: "push small int 3", val: 3, expected: []byte{btcscript.OP_3}}, + {name: "push small int 4", val: 4, expected: []byte{btcscript.OP_4}}, + {name: "push small int 5", val: 5, expected: []byte{btcscript.OP_5}}, + {name: "push small int 6", val: 6, expected: []byte{btcscript.OP_6}}, + {name: "push small int 7", val: 7, expected: []byte{btcscript.OP_7}}, + {name: "push small int 8", val: 8, expected: []byte{btcscript.OP_8}}, + {name: "push small int 9", val: 9, expected: []byte{btcscript.OP_9}}, + {name: "push small int 10", val: 10, expected: []byte{btcscript.OP_10}}, + {name: "push small int 11", val: 11, expected: []byte{btcscript.OP_11}}, + {name: "push small int 12", val: 12, expected: []byte{btcscript.OP_12}}, + {name: "push small int 13", val: 13, expected: []byte{btcscript.OP_13}}, + {name: "push small int 14", val: 14, expected: []byte{btcscript.OP_14}}, + {name: "push small int 15", val: 15, expected: []byte{btcscript.OP_15}}, + {name: "push small int 16", val: 16, expected: []byte{btcscript.OP_16}}, + {name: "push 17", val: 17, expected: []byte{btcscript.OP_DATA_1, 0x11}}, + {name: "push 65", val: 65, expected: []byte{btcscript.OP_DATA_1, 0x41}}, + {name: "push 127", val: 127, expected: []byte{btcscript.OP_DATA_1, 0x7f}}, + {name: "push 128", val: 128, expected: []byte{btcscript.OP_DATA_2, 0x80, 0}}, + {name: "push 255", val: 255, expected: []byte{btcscript.OP_DATA_2, 0xff, 0}}, + {name: "push 256", val: 256, expected: []byte{btcscript.OP_DATA_2, 0, 0x01}}, + {name: "push 32767", val: 32767, expected: []byte{btcscript.OP_DATA_2, 0xff, 0x7f}}, + {name: "push 32768", val: 32768, expected: []byte{btcscript.OP_DATA_3, 0, 0x80, 0}}, + {name: "push -2", val: -2, expected: []byte{btcscript.OP_DATA_1, 0x82}}, + {name: "push -3", val: -3, expected: []byte{btcscript.OP_DATA_1, 0x83}}, + {name: "push -4", val: -4, expected: []byte{btcscript.OP_DATA_1, 0x84}}, + {name: "push -5", val: -5, expected: []byte{btcscript.OP_DATA_1, 0x85}}, + {name: "push -17", val: -17, expected: []byte{btcscript.OP_DATA_1, 0x91}}, + {name: "push -65", val: -65, expected: []byte{btcscript.OP_DATA_1, 0xc1}}, + {name: "push -127", val: -127, expected: []byte{btcscript.OP_DATA_1, 0xff}}, + {name: "push -128", val: -128, expected: []byte{btcscript.OP_DATA_2, 0x80, 0x80}}, + {name: "push -255", val: -255, expected: []byte{btcscript.OP_DATA_2, 0xff, 0x80}}, + {name: "push -256", val: -256, expected: []byte{btcscript.OP_DATA_2, 0x00, 0x81}}, + {name: "push -32767", val: -32767, expected: []byte{btcscript.OP_DATA_2, 0xff, 0xff}}, + {name: "push -32768", val: -32768, expected: []byte{btcscript.OP_DATA_3, 0x00, 0x80, 0x80}}, + } + + builder := btcscript.NewScriptBuilder() + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + builder.Reset().PushInt64(test.val) + result := builder.Script() + if !bytes.Equal(result, test.expected) { + t.Errorf("ScriptBuilder.PushInt64 #%d (%s) wrong result\n"+ + "got: %x\nwant: %x", i, test.name, result, + test.expected) + continue + } + } +} + +// TestScriptBuilderPushUint64 tests that pushing unsigned integers to a script +// via the ScriptBuilder API works as expected. +func TestScriptBuilderPushUint64(t *testing.T) { + tests := []struct { + name string + val uint64 + expected []byte + }{ + {name: "push small int 0", val: 0, expected: []byte{btcscript.OP_0}}, + {name: "push small int 1", val: 1, expected: []byte{btcscript.OP_1}}, + {name: "push small int 2", val: 2, expected: []byte{btcscript.OP_2}}, + {name: "push small int 3", val: 3, expected: []byte{btcscript.OP_3}}, + {name: "push small int 4", val: 4, expected: []byte{btcscript.OP_4}}, + {name: "push small int 5", val: 5, expected: []byte{btcscript.OP_5}}, + {name: "push small int 6", val: 6, expected: []byte{btcscript.OP_6}}, + {name: "push small int 7", val: 7, expected: []byte{btcscript.OP_7}}, + {name: "push small int 8", val: 8, expected: []byte{btcscript.OP_8}}, + {name: "push small int 9", val: 9, expected: []byte{btcscript.OP_9}}, + {name: "push small int 10", val: 10, expected: []byte{btcscript.OP_10}}, + {name: "push small int 11", val: 11, expected: []byte{btcscript.OP_11}}, + {name: "push small int 12", val: 12, expected: []byte{btcscript.OP_12}}, + {name: "push small int 13", val: 13, expected: []byte{btcscript.OP_13}}, + {name: "push small int 14", val: 14, expected: []byte{btcscript.OP_14}}, + {name: "push small int 15", val: 15, expected: []byte{btcscript.OP_15}}, + {name: "push small int 16", val: 16, expected: []byte{btcscript.OP_16}}, + {name: "push 17", val: 17, expected: []byte{btcscript.OP_DATA_1, 0x11}}, + {name: "push 65", val: 65, expected: []byte{btcscript.OP_DATA_1, 0x41}}, + {name: "push 127", val: 127, expected: []byte{btcscript.OP_DATA_1, 0x7f}}, + {name: "push 128", val: 128, expected: []byte{btcscript.OP_DATA_2, 0x80, 0}}, + {name: "push 255", val: 255, expected: []byte{btcscript.OP_DATA_2, 0xff, 0}}, + {name: "push 256", val: 256, expected: []byte{btcscript.OP_DATA_2, 0, 0x01}}, + {name: "push 32767", val: 32767, expected: []byte{btcscript.OP_DATA_2, 0xff, 0x7f}}, + {name: "push 32768", val: 32768, expected: []byte{btcscript.OP_DATA_3, 0, 0x80, 0}}, + } + + builder := btcscript.NewScriptBuilder() + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + builder.Reset().PushUint64(test.val) + result := builder.Script() + if !bytes.Equal(result, test.expected) { + t.Errorf("ScriptBuilder.PushUint64 #%d (%s) wrong result\n"+ + "got: %x\nwant: %x", i, test.name, result, + test.expected) + continue + } + } +} + +// TestScriptBuilderPushData tests that pushing data to a script via the +// ScriptBuilder API works as expected. +func TestScriptBuilderPushData(t *testing.T) { + tests := []struct { + name string + data []byte + expected []byte + }{ + // Start off with the small ints to ensure canonical encoding. + {name: "push small int 0", data: []byte{0}, expected: []byte{btcscript.OP_0}}, + {name: "push small int 1", data: []byte{1}, expected: []byte{btcscript.OP_1}}, + {name: "push small int 2", data: []byte{2}, expected: []byte{btcscript.OP_2}}, + {name: "push small int 3", data: []byte{3}, expected: []byte{btcscript.OP_3}}, + {name: "push small int 4", data: []byte{4}, expected: []byte{btcscript.OP_4}}, + {name: "push small int 5", data: []byte{5}, expected: []byte{btcscript.OP_5}}, + {name: "push small int 6", data: []byte{6}, expected: []byte{btcscript.OP_6}}, + {name: "push small int 7", data: []byte{7}, expected: []byte{btcscript.OP_7}}, + {name: "push small int 8", data: []byte{8}, expected: []byte{btcscript.OP_8}}, + {name: "push small int 9", data: []byte{9}, expected: []byte{btcscript.OP_9}}, + {name: "push small int 10", data: []byte{10}, expected: []byte{btcscript.OP_10}}, + {name: "push small int 11", data: []byte{11}, expected: []byte{btcscript.OP_11}}, + {name: "push small int 12", data: []byte{12}, expected: []byte{btcscript.OP_12}}, + {name: "push small int 13", data: []byte{13}, expected: []byte{btcscript.OP_13}}, + {name: "push small int 14", data: []byte{14}, expected: []byte{btcscript.OP_14}}, + {name: "push small int 15", data: []byte{15}, expected: []byte{btcscript.OP_15}}, + {name: "push small int 16", data: []byte{16}, expected: []byte{btcscript.OP_16}}, + + // 1-byte data push opcodes. + { + name: "push data len 17", + data: bytes.Repeat([]byte{0x49}, 17), + expected: append([]byte{btcscript.OP_DATA_17}, bytes.Repeat([]byte{0x49}, 17)...), + }, + { + name: "push data len 75", + data: bytes.Repeat([]byte{0x49}, 75), + expected: append([]byte{btcscript.OP_DATA_75}, bytes.Repeat([]byte{0x49}, 75)...), + }, + + // 2-byte data push via OP_PUSHDATA_1. + { + name: "push data len 76", + data: bytes.Repeat([]byte{0x49}, 76), + expected: append([]byte{btcscript.OP_PUSHDATA1, 76}, bytes.Repeat([]byte{0x49}, 76)...), + }, + { + name: "push data len 255", + data: bytes.Repeat([]byte{0x49}, 255), + expected: append([]byte{btcscript.OP_PUSHDATA1, 255}, bytes.Repeat([]byte{0x49}, 255)...), + }, + + // 3-byte data push via OP_PUSHDATA_2. + { + name: "push data len 256", + data: bytes.Repeat([]byte{0x49}, 256), + expected: append([]byte{btcscript.OP_PUSHDATA2, 0, 1}, bytes.Repeat([]byte{0x49}, 256)...), + }, + { + name: "push data len 32767", + data: bytes.Repeat([]byte{0x49}, 32767), + expected: append([]byte{btcscript.OP_PUSHDATA2, 255, 127}, bytes.Repeat([]byte{0x49}, 32767)...), + }, + + // 5-byte data push via OP_PUSHDATA_4. + { + name: "push data len 65536", + data: bytes.Repeat([]byte{0x49}, 65536), + expected: append([]byte{btcscript.OP_PUSHDATA4, 0, 0, 1, 0}, bytes.Repeat([]byte{0x49}, 65536)...), + }, + } + + builder := btcscript.NewScriptBuilder() + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + builder.Reset().PushData(test.data) + result := builder.Script() + if !bytes.Equal(result, test.expected) { + t.Errorf("ScriptBuilder.PushData #%d (%s) wrong result\n"+ + "got: %x\nwant: %x", i, test.name, result, + test.expected) + continue + } + } +} diff --git a/test_coverage.txt b/test_coverage.txt index 3fa16760..908cb33d 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -6,152 +6,160 @@ github.com/conformal/btcscript/address.go ExtractPkScriptAddrs 100.00% (27/27 github.com/conformal/btcscript/script.go CalcScriptInfo 100.00% (25/25) github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23) github.com/conformal/btcscript/script.go NewScript 100.00% (21/21) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.PushData 100.00% (21/21) github.com/conformal/btcscript/stack.go asInt 100.00% (21/21) -github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (16/16) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (16/16) +github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (16/16) github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (14/14) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) -github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) +github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) +github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) +github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) -github.com/conformal/btcscript/script.go PayToAddrScript 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) -github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/script.go PayToAddrScript 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) -github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) +github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.PushInt64 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) github.com/conformal/btcscript/script.go unparseScript 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) +github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/script.go typeOfScript 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.PushUint64 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) -github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (4/4) -github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) -github.com/conformal/btcscript/script.go getStack 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/script.go getStack 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) +github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) +github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) github.com/conformal/btcscript/script.go isNullData 100.00% (4/4) -github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) +github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) +github.com/conformal/btcscript/script.go isSmallInt 100.00% (3/3) github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) github.com/conformal/btcscript/script.go ScriptClass.String 100.00% (3/3) +github.com/conformal/btcscript/script.go asSmallInt 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) github.com/conformal/btcscript/script.go setStack 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) -github.com/conformal/btcscript/script.go isSmallInt 100.00% (3/3) -github.com/conformal/btcscript/script.go asSmallInt 100.00% (3/3) -github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) +github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.PushOp 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) -github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) -github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) -github.com/conformal/btcscript/script.go PayToPubKeyHashScript 100.00% (2/2) github.com/conformal/btcscript/script.go PayToScriptHashScript 100.00% (2/2) -github.com/conformal/btcscript/log.go init 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Reset 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) +github.com/conformal/btcscript/script.go PayToPubKeyHashScript 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) -github.com/conformal/btcscript/opcode.go init 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) -github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) -github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) +github.com/conformal/btcscript/log.go init 100.00% (1/1) github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) +github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) +github.com/conformal/btcscript/opcode.go init 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) +github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) +github.com/conformal/btcscript/scriptbuilder.go NewScriptBuilder 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckSig 90.00% (27/30) github.com/conformal/btcscript/script.go expectedInputs 85.71% (6/7) github.com/conformal/btcscript/script.go calcScriptHash 82.05% (32/39) github.com/conformal/btcscript/script.go Script.CheckErrorCondition 78.57% (11/14) +github.com/conformal/btcscript/script.go IsPushOnlyScript 75.00% (3/4) github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) +github.com/conformal/btcscript/script.go HasCanonicalPushes 66.67% (12/18) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/10) github.com/conformal/btcscript/script.go CalcMultiSigStats 0.00% (0/8) -github.com/conformal/btcscript/script.go IsPushOnlyScript 0.00% (0/4) github.com/conformal/btcscript/log.go UseLogger 0.00% (0/1) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript --------------------------- 95.22% (976/1025) +github.com/conformal/btcscript --------------------------- 95.20% (1032/1084) From cff7f9704b861e8d8039bc1b7042ee1ec7a8d3f1 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 20 Feb 2014 11:19:48 -0600 Subject: [PATCH 097/174] Fix a few comment typos. --- address.go | 2 +- script.go | 2 +- scriptbuilder.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/address.go b/address.go index f0f0eae0..b23f1b32 100644 --- a/address.go +++ b/address.go @@ -40,7 +40,7 @@ func ExtractPkScriptAddrs(pkScript []byte, net btcwire.BitcoinNet) (ScriptClass, case PubKeyTy: // A pay-to-pubkey script is of the form: // OP_CHECKSIG - // Therefore the pubkey is the item on the stack. + // Therefore the pubkey is the first item on the stack. // Skip the pubkey if it's invalid for some reason. requiredSigs = 1 addr, err := btcutil.NewAddressPubKey(pops[0].data, net) diff --git a/script.go b/script.go index bd3b90cb..4baa5850 100644 --- a/script.go +++ b/script.go @@ -1122,7 +1122,7 @@ func signatureScriptCustomReader(reader io.Reader, tx *btcwire.MsgTx, idx int, // expectedInputs returns the number of arguments required by a script. // If the script is of unnown type such that the number can not be determined -// then -1 is returned. We are an interanl function and thus assume that class +// then -1 is returned. We are an internal function and thus assume that class // is the real class of pops (and we can thus assume things that were // determined while finding out the type). func expectedInputs(pops []parsedOpcode, class ScriptClass) int { diff --git a/scriptbuilder.go b/scriptbuilder.go index d7980621..b4f2c838 100644 --- a/scriptbuilder.go +++ b/scriptbuilder.go @@ -19,7 +19,7 @@ const ( ) // ScriptBuilder provides a facility for building custom scripts. It allows -// you to push opcodes, ints, and, data while respecting canonical encoding. It +// you to push opcodes, ints, and data while respecting canonical encoding. It // does not ensure the script will execute correctly. // // For example, the following would build a 2-of-3 multisig script for usage in From 1566366346f8ebbf053b35edeb8e1dfa235bd3fc Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Thu, 20 Feb 2014 17:39:03 +0000 Subject: [PATCH 098/174] convert internal script generation to use ScriptBuilder. Also, unexport the functions to generate script types. Everything should (and is) be using PayToAddrScript() with an address type instead of throwing bytes around. discussed with #@davecgh --- script.go | 77 ++++------------- script_test.go | 27 ------ test_coverage.txt | 216 +++++++++++++++++++++++----------------------- 3 files changed, 129 insertions(+), 191 deletions(-) diff --git a/script.go b/script.go index 4baa5850..3b69faa2 100644 --- a/script.go +++ b/script.go @@ -1001,46 +1001,20 @@ func getSigOpCount(pops []parsedOpcode, precise bool) int { return nSigs } -// PayToPubKeyHashScript creates a new script to pay a transaction -// output to a 20-byte pubkey hash. -func PayToPubKeyHashScript(pubKeyHash []byte) (pkScript []byte, err error) { - pops := []parsedOpcode{ - { - opcode: opcodemap[OP_DUP], - }, - { - opcode: opcodemap[OP_HASH160], - }, - { - opcode: opcodemap[OP_DATA_20], - data: pubKeyHash, - }, - { - opcode: opcodemap[OP_EQUALVERIFY], - }, - { - opcode: opcodemap[OP_CHECKSIG], - }, - } - return unparseScript(pops) +// payToPubKeyHashScript creates a new script to pay a transaction +// output to a 20-byte pubkey hash. It is expected that the input is a valid +// hash. +func payToPubKeyHashScript(pubKeyHash []byte) []byte { + return NewScriptBuilder().PushOp(OP_DUP).PushOp(OP_HASH160). + PushData(pubKeyHash).PushOp(OP_EQUALVERIFY).PushOp(OP_CHECKSIG). + Script() } -// PayToScriptHashScript creates a new script to pay a transaction output to a -// script hash. -func PayToScriptHashScript(scriptHash []byte) (pkScript []byte, err error) { - pops := []parsedOpcode{ - { - opcode: opcodemap[OP_HASH160], - }, - { - opcode: opcodemap[OP_DATA_20], - data: scriptHash, - }, - { - opcode: opcodemap[OP_EQUAL], - }, - } - return unparseScript(pops) +// payToScriptHashScript creates a new script to pay a transaction output to a +// script hash. It is expected that the input is a valid hash. +func payToScriptHashScript(scriptHash []byte) []byte { + return NewScriptBuilder().PushOp(OP_HASH160).PushData(scriptHash). + PushOp(OP_EQUAL).Script() } // PayToAddrScript creates a new script to pay a transaction output to a the @@ -1052,13 +1026,13 @@ func PayToAddrScript(addr btcutil.Address) ([]byte, error) { if addr == nil { return nil, ErrUnsupportedAddress } - return PayToPubKeyHashScript(addr.ScriptAddress()) + return payToPubKeyHashScript(addr.ScriptAddress()), nil case *btcutil.AddressScriptHash: if addr == nil { return nil, ErrUnsupportedAddress } - return PayToScriptHashScript(addr.ScriptAddress()) + return payToScriptHashScript(addr.ScriptAddress()), nil } return nil, ErrUnsupportedAddress @@ -1074,7 +1048,6 @@ func PayToAddrScript(addr btcutil.Address) ([]byte, error) { // compress. This format must match the same format used to generate // the payment address, or the script validation will fail. func SignatureScript(tx *btcwire.MsgTx, idx int, subscript []byte, hashType byte, privkey *ecdsa.PrivateKey, compress bool) ([]byte, error) { - return signatureScriptCustomReader(rand.Reader, tx, idx, subscript, hashType, privkey, compress) } @@ -1098,26 +1071,14 @@ func signatureScriptCustomReader(reader io.Reader, tx *btcwire.MsgTx, idx int, sig := append(ecSig.Serialize(), hashType) pk := (*btcec.PublicKey)(&privkey.PublicKey) - var pubkeyOpcode *parsedOpcode + var pkData []byte if compress { - pubkeyOpcode = &parsedOpcode{ - opcode: opcodemap[OP_DATA_33], - data: pk.SerializeCompressed(), - } + pkData = pk.SerializeCompressed() } else { - pubkeyOpcode = &parsedOpcode{ - opcode: opcodemap[OP_DATA_65], - data: pk.SerializeUncompressed(), - } + pkData = pk.SerializeUncompressed() } - pops := []parsedOpcode{ - { - opcode: opcodemap[byte(len(sig))], - data: sig, - }, - *pubkeyOpcode, - } - return unparseScript(pops) + + return NewScriptBuilder().PushData(sig).PushData(pkData).Script(), nil } // expectedInputs returns the number of arguments required by a script. diff --git a/script_test.go b/script_test.go index 3f193016..3156f0fb 100644 --- a/script_test.go +++ b/script_test.go @@ -2429,33 +2429,6 @@ func TestCheckErrorCondition(t *testing.T) { } } -func TestPayToPubKeyHashScript(t *testing.T) { - validaddr := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20} - invalidaddr := validaddr[:len(validaddr)-2] - - expected := []byte{btcscript.OP_DUP, btcscript.OP_HASH160, - btcscript.OP_DATA_20, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, btcscript.OP_EQUALVERIFY, - btcscript.OP_CHECKSIG} - - script, err := btcscript.PayToPubKeyHashScript(validaddr) - if err != nil { - t.Error(err) - return - } - if !bytes.Equal(script, expected) { - t.Error("Unexpected script result.") - return - } - - _, err = btcscript.PayToPubKeyHashScript(invalidaddr) - if err == nil { - t.Error("Erroneously created script for invalid address.") - return - } -} - type TstSigScript struct { name string inputs []TstInput diff --git a/test_coverage.txt b/test_coverage.txt index 908cb33d..f0c1889c 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -1,165 +1,169 @@ github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 100.00% (62/62) -github.com/conformal/btcscript/script.go Script.Step 100.00% (37/37) +github.com/conformal/btcscript/script.go Script.Step 100.00% (38/38) github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (30/30) github.com/conformal/btcscript/address.go ExtractPkScriptAddrs 100.00% (27/27) github.com/conformal/btcscript/script.go CalcScriptInfo 100.00% (25/25) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.PushData 100.00% (24/24) github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23) -github.com/conformal/btcscript/script.go NewScript 100.00% (21/21) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.PushData 100.00% (21/21) github.com/conformal/btcscript/stack.go asInt 100.00% (21/21) +github.com/conformal/btcscript/script.go NewScript 100.00% (21/21) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (16/16) -github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (16/16) -github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (14/14) +github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (15/15) +github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (15/15) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) +github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) -github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) +github.com/conformal/btcscript/script.go Script.CheckErrorCondition 100.00% (11/11) +github.com/conformal/btcscript/script.go typeOfScript 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) -github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) -github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) +github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) +github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) +github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) -github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) +github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) +github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/script.go Script.Execute 100.00% (8/8) github.com/conformal/btcscript/script.go PayToAddrScript 100.00% (8/8) +github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) -github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.PushInt64 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) -github.com/conformal/btcscript/script.go unparseScript 100.00% (7/7) -github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) -github.com/conformal/btcscript/script.go typeOfScript 100.00% (7/7) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.PushUint64 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.PushInt64 100.00% (7/7) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.PushUint64 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) +github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/script.go getStack 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) -github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) -github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) -github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) -github.com/conformal/btcscript/script.go isNullData 100.00% (4/4) -github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) +github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) +github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) +github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) +github.com/conformal/btcscript/script.go isNullData 100.00% (4/4) +github.com/conformal/btcscript/script.go getStack 100.00% (4/4) +github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) +github.com/conformal/btcscript/script.go setStack 100.00% (3/3) +github.com/conformal/btcscript/script.go asSmallInt 100.00% (3/3) github.com/conformal/btcscript/script.go isSmallInt 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) github.com/conformal/btcscript/script.go ScriptClass.String 100.00% (3/3) -github.com/conformal/btcscript/script.go asSmallInt 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) -github.com/conformal/btcscript/script.go setStack 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) -github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.PushOp 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/conformal/btcscript/script.go PayToScriptHashScript 100.00% (2/2) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Reset 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) -github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) -github.com/conformal/btcscript/script.go PayToPubKeyHashScript 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) -github.com/conformal/btcscript/log.go init 100.00% (1/1) -github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) -github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/opcode.go init 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) +github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.PushOp 100.00% (2/2) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Reset 100.00% (2/2) github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) +github.com/conformal/btcscript/log.go init 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) -github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) +github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go init 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) +github.com/conformal/btcscript/script.go payToPubKeyHashScript 100.00% (1/1) +github.com/conformal/btcscript/script.go payToScriptHashScript 100.00% (1/1) +github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) +github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) github.com/conformal/btcscript/scriptbuilder.go NewScriptBuilder 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeCheckSig 90.00% (27/30) +github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeCheckSig 93.10% (27/29) +github.com/conformal/btcscript/script.go unparseScript 85.71% (6/7) github.com/conformal/btcscript/script.go expectedInputs 85.71% (6/7) github.com/conformal/btcscript/script.go calcScriptHash 82.05% (32/39) -github.com/conformal/btcscript/script.go Script.CheckErrorCondition 78.57% (11/14) -github.com/conformal/btcscript/script.go IsPushOnlyScript 75.00% (3/4) github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) +github.com/conformal/btcscript/script.go IsPushOnlyScript 75.00% (3/4) github.com/conformal/btcscript/script.go HasCanonicalPushes 66.67% (12/18) -github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/10) github.com/conformal/btcscript/script.go CalcMultiSigStats 0.00% (0/8) +github.com/conformal/btcscript/script.go @540:34 0.00% (0/6) +github.com/conformal/btcscript/script.go @528:34 0.00% (0/4) +github.com/conformal/btcscript/script.go @573:34 0.00% (0/3) github.com/conformal/btcscript/log.go UseLogger 0.00% (0/1) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript --------------------------- 95.20% (1032/1084) +github.com/conformal/btcscript/opcode.go @1741:33 0.00% (0/1) +github.com/conformal/btcscript --------------------------- 95.14% (1037/1090) From 5171cb803cf2efa82ad04d66c81530fe3d560660 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Thu, 20 Feb 2014 17:42:06 +0000 Subject: [PATCH 099/174] Convert builder.Push* to builder.Add* we think this is clearer. Also, shorter! Discussed with @davecgh. --- script.go | 10 +++++----- script_test.go | 4 ++-- scriptbuilder.go | 26 +++++++++++++------------- scriptbuilder_test.go | 32 ++++++++++++++++---------------- test_coverage.txt | 8 ++++---- 5 files changed, 40 insertions(+), 40 deletions(-) diff --git a/script.go b/script.go index 3b69faa2..901247c6 100644 --- a/script.go +++ b/script.go @@ -1005,16 +1005,16 @@ func getSigOpCount(pops []parsedOpcode, precise bool) int { // output to a 20-byte pubkey hash. It is expected that the input is a valid // hash. func payToPubKeyHashScript(pubKeyHash []byte) []byte { - return NewScriptBuilder().PushOp(OP_DUP).PushOp(OP_HASH160). - PushData(pubKeyHash).PushOp(OP_EQUALVERIFY).PushOp(OP_CHECKSIG). + return NewScriptBuilder().AddOp(OP_DUP).AddOp(OP_HASH160). + AddData(pubKeyHash).AddOp(OP_EQUALVERIFY).AddOp(OP_CHECKSIG). Script() } // payToScriptHashScript creates a new script to pay a transaction output to a // script hash. It is expected that the input is a valid hash. func payToScriptHashScript(scriptHash []byte) []byte { - return NewScriptBuilder().PushOp(OP_HASH160).PushData(scriptHash). - PushOp(OP_EQUAL).Script() + return NewScriptBuilder().AddOp(OP_HASH160).AddData(scriptHash). + AddOp(OP_EQUAL).Script() } // PayToAddrScript creates a new script to pay a transaction output to a the @@ -1078,7 +1078,7 @@ func signatureScriptCustomReader(reader io.Reader, tx *btcwire.MsgTx, idx int, pkData = pk.SerializeUncompressed() } - return NewScriptBuilder().PushData(sig).PushData(pkData).Script(), nil + return NewScriptBuilder().AddData(sig).AddData(pkData).Script(), nil } // expectedInputs returns the number of arguments required by a script. diff --git a/script_test.go b/script_test.go index 3156f0fb..90d5c171 100644 --- a/script_test.go +++ b/script_test.go @@ -18,7 +18,7 @@ import ( func TestStandardPushes(t *testing.T) { for i := 0; i < 1000; i++ { builder := btcscript.NewScriptBuilder() - builder.PushInt64(int64(i)) + builder.AddInt64(int64(i)) if result := btcscript.IsPushOnlyScript(builder.Script()); !result { t.Errorf("StandardPushesTests IsPushOnlyScript test #%d failed: %x\n", i, builder.Script()) } @@ -29,7 +29,7 @@ func TestStandardPushes(t *testing.T) { } for i := 0; i < 1000; i++ { builder := btcscript.NewScriptBuilder() - builder.PushData(bytes.Repeat([]byte{0x49}, i)) + builder.AddData(bytes.Repeat([]byte{0x49}, i)) if result := btcscript.IsPushOnlyScript(builder.Script()); !result { t.Errorf("StandardPushesTests IsPushOnlyScript test #%d failed: %x\n", i, builder.Script()) } diff --git a/scriptbuilder.go b/scriptbuilder.go index b4f2c838..b623dde3 100644 --- a/scriptbuilder.go +++ b/scriptbuilder.go @@ -25,23 +25,23 @@ const ( // For example, the following would build a 2-of-3 multisig script for usage in // a pay-to-script-hash: // builder := btcscript.NewScriptBuilder() -// builder.PushOp(btcscript.OP_2).PushData(pubKey1).PushData(pubKey2) -// builder.PushData(pubKey3).PushOp(btcscript.OP_3) -// builder.PushOp(btcscript.OP_CHECKMULTISIG) +// builder.AddOp(btcscript.OP_2).AddData(pubKey1).AddData(pubKey2) +// builder.AddData(pubKey3).AddOp(btcscript.OP_3) +// builder.AddOp(btcscript.OP_CHECKMULTISIG) // fmt.Printf("Final multi-sig script: %x\n", builder.Script()) type ScriptBuilder struct { script []byte } -// PushOp pushes the passed opcode to the end of the script. -func (b *ScriptBuilder) PushOp(opcode byte) *ScriptBuilder { +// AddOp pushes the passed opcode to the end of the script. +func (b *ScriptBuilder) AddOp(opcode byte) *ScriptBuilder { b.script = append(b.script, opcode) return b } -// PushData pushes the passed data to the end of the script. It automatically +// AddData pushes the passed data to the end of the script. It automatically // chooses canonical opcodes depending on the length of the data. -func (b *ScriptBuilder) PushData(data []byte) *ScriptBuilder { +func (b *ScriptBuilder) AddData(data []byte) *ScriptBuilder { // Don't modify the script at all if no data was passed. dataLen := len(data) if dataLen == 0 { @@ -85,8 +85,8 @@ func (b *ScriptBuilder) PushData(data []byte) *ScriptBuilder { return b } -// PushInt64 pushes the passed integer to the end of the script. -func (b *ScriptBuilder) PushInt64(val int64) *ScriptBuilder { +// AddInt64 pushes the passed integer to the end of the script. +func (b *ScriptBuilder) AddInt64(val int64) *ScriptBuilder { // Fast path for small integers and OP_1NEGATE. if val == 0 { b.script = append(b.script, OP_0) @@ -97,11 +97,11 @@ func (b *ScriptBuilder) PushInt64(val int64) *ScriptBuilder { return b } - return b.PushData(fromInt(new(big.Int).SetInt64(val))) + return b.AddData(fromInt(new(big.Int).SetInt64(val))) } -// PushUint64 pushes the passed integer to the end of the script. -func (b *ScriptBuilder) PushUint64(val uint64) *ScriptBuilder { +// AddUint64 pushes the passed integer to the end of the script. +func (b *ScriptBuilder) AddUint64(val uint64) *ScriptBuilder { // Fast path for small integers. if val == 0 { b.script = append(b.script, OP_0) @@ -112,7 +112,7 @@ func (b *ScriptBuilder) PushUint64(val uint64) *ScriptBuilder { return b } - return b.PushData(fromInt(new(big.Int).SetUint64(val))) + return b.AddData(fromInt(new(big.Int).SetUint64(val))) } // Reset resets the script so it has no content. diff --git a/scriptbuilder_test.go b/scriptbuilder_test.go index 08b3398c..847f53b8 100644 --- a/scriptbuilder_test.go +++ b/scriptbuilder_test.go @@ -10,9 +10,9 @@ import ( "testing" ) -// TestScriptBuilderPushOp tests that pushing opcodes to a script via the +// TestScriptBuilderAddOp tests that pushing opcodes to a script via the // ScriptBuilder API works as expected. -func TestScriptBuilderPushOp(t *testing.T) { +func TestScriptBuilderAddOp(t *testing.T) { tests := []struct { name string opcodes []byte @@ -40,11 +40,11 @@ func TestScriptBuilderPushOp(t *testing.T) { for i, test := range tests { builder.Reset() for _, opcode := range test.opcodes { - builder.PushOp(opcode) + builder.AddOp(opcode) } result := builder.Script() if !bytes.Equal(result, test.expected) { - t.Errorf("ScriptBuilder.PushOp #%d (%s) wrong result\n"+ + t.Errorf("ScriptBuilder.AddOp #%d (%s) wrong result\n"+ "got: %x\nwant: %x", i, test.name, result, test.expected) continue @@ -52,9 +52,9 @@ func TestScriptBuilderPushOp(t *testing.T) { } } -// TestScriptBuilderPushInt64 tests that pushing signed integers to a script via +// TestScriptBuilderAddInt64 tests that pushing signed integers to a script via // the ScriptBuilder API works as expected. -func TestScriptBuilderPushInt64(t *testing.T) { +func TestScriptBuilderAddInt64(t *testing.T) { tests := []struct { name string val int64 @@ -103,10 +103,10 @@ func TestScriptBuilderPushInt64(t *testing.T) { builder := btcscript.NewScriptBuilder() t.Logf("Running %d tests", len(tests)) for i, test := range tests { - builder.Reset().PushInt64(test.val) + builder.Reset().AddInt64(test.val) result := builder.Script() if !bytes.Equal(result, test.expected) { - t.Errorf("ScriptBuilder.PushInt64 #%d (%s) wrong result\n"+ + t.Errorf("ScriptBuilder.AddInt64 #%d (%s) wrong result\n"+ "got: %x\nwant: %x", i, test.name, result, test.expected) continue @@ -114,9 +114,9 @@ func TestScriptBuilderPushInt64(t *testing.T) { } } -// TestScriptBuilderPushUint64 tests that pushing unsigned integers to a script +// TestScriptBuilderAddUint64 tests that pushing unsigned integers to a script // via the ScriptBuilder API works as expected. -func TestScriptBuilderPushUint64(t *testing.T) { +func TestScriptBuilderAddUint64(t *testing.T) { tests := []struct { name string val uint64 @@ -152,10 +152,10 @@ func TestScriptBuilderPushUint64(t *testing.T) { builder := btcscript.NewScriptBuilder() t.Logf("Running %d tests", len(tests)) for i, test := range tests { - builder.Reset().PushUint64(test.val) + builder.Reset().AddUint64(test.val) result := builder.Script() if !bytes.Equal(result, test.expected) { - t.Errorf("ScriptBuilder.PushUint64 #%d (%s) wrong result\n"+ + t.Errorf("ScriptBuilder.AddUint64 #%d (%s) wrong result\n"+ "got: %x\nwant: %x", i, test.name, result, test.expected) continue @@ -163,9 +163,9 @@ func TestScriptBuilderPushUint64(t *testing.T) { } } -// TestScriptBuilderPushData tests that pushing data to a script via the +// TestScriptBuilderAddData tests that pushing data to a script via the // ScriptBuilder API works as expected. -func TestScriptBuilderPushData(t *testing.T) { +func TestScriptBuilderAddData(t *testing.T) { tests := []struct { name string data []byte @@ -237,10 +237,10 @@ func TestScriptBuilderPushData(t *testing.T) { builder := btcscript.NewScriptBuilder() t.Logf("Running %d tests", len(tests)) for i, test := range tests { - builder.Reset().PushData(test.data) + builder.Reset().AddData(test.data) result := builder.Script() if !bytes.Equal(result, test.expected) { - t.Errorf("ScriptBuilder.PushData #%d (%s) wrong result\n"+ + t.Errorf("ScriptBuilder.AddData #%d (%s) wrong result\n"+ "got: %x\nwant: %x", i, test.name, result, test.expected) continue diff --git a/test_coverage.txt b/test_coverage.txt index f0c1889c..c6000c10 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -4,7 +4,7 @@ github.com/conformal/btcscript/script.go Script.Step 100.00% (38/38) github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (30/30) github.com/conformal/btcscript/address.go ExtractPkScriptAddrs 100.00% (27/27) github.com/conformal/btcscript/script.go CalcScriptInfo 100.00% (25/25) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.PushData 100.00% (24/24) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddData 100.00% (24/24) github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23) github.com/conformal/btcscript/stack.go asInt 100.00% (21/21) github.com/conformal/btcscript/script.go NewScript 100.00% (21/21) @@ -43,8 +43,8 @@ github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.PushInt64 100.00% (7/7) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.PushUint64 100.00% (7/7) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddInt64 100.00% (7/7) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddUint64 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) @@ -106,7 +106,7 @@ github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.PushOp 100.00% (2/2) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddOp 100.00% (2/2) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Reset 100.00% (2/2) github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) From 2b0b512a83acb2bdfa9766b7dc44b6f81cb89c02 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Thu, 20 Feb 2014 18:37:42 +0000 Subject: [PATCH 100/174] Add support for pay to pubkey addresses to PayToAddrScript Based on some initial code from @davecgh, finished by me. --- script.go | 16 ++++- script_test.go | 80 +++++++++++++++++++++++ test_coverage.txt | 161 +++++++++++++++++++++++----------------------- 3 files changed, 175 insertions(+), 82 deletions(-) diff --git a/script.go b/script.go index 901247c6..0ab0b36d 100644 --- a/script.go +++ b/script.go @@ -1017,9 +1017,15 @@ func payToScriptHashScript(scriptHash []byte) []byte { AddOp(OP_EQUAL).Script() } +// payToPubkeyScript creates a new script to pay a transaction output to a +// public key. It is expected that the input is a valid pubkey. +func payToPubKeyScript(serializedPubKey []byte) []byte { + return NewScriptBuilder().AddData(serializedPubKey). + AddOp(OP_CHECKSIG).Script() +} + // PayToAddrScript creates a new script to pay a transaction output to a the -// specified address. Currently the only supported address types are -// btcutil.AddressPubKeyHash and btcutil.AddressScriptHash. +// specified address. func PayToAddrScript(addr btcutil.Address) ([]byte, error) { switch addr := addr.(type) { case *btcutil.AddressPubKeyHash: @@ -1033,6 +1039,12 @@ func PayToAddrScript(addr btcutil.Address) ([]byte, error) { return nil, ErrUnsupportedAddress } return payToScriptHashScript(addr.ScriptAddress()), nil + + case *btcutil.AddressPubKey: + if addr == nil { + return nil, ErrUnsupportedAddress + } + return payToPubKeyScript(addr.ScriptAddress()), nil } return nil, ErrUnsupportedAddress diff --git a/script_test.go b/script_test.go index 90d5c171..003818a8 100644 --- a/script_test.go +++ b/script_test.go @@ -2885,6 +2885,42 @@ func TestPayToAddrScript(t *testing.T) { return } + // mainnet p2pk 13CG6SJ3yHUXo4Cr2RY4THLLJrNFuG3gUg + p2pkCompressedMain, err := btcutil.NewAddressPubKey([]byte{ + 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94 , 0x34, 0x4c, 0x95, + 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d , 0x8d, 0x79, 0x03, + 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24 , 0x89, 0x5d, 0xca, + 0x52, 0xc6, 0xb4}, btcwire.MainNet) + if err != nil { + t.Errorf("Unable to create pubkey address (compressed): %v", + err) + return + } + p2pkCompressed2Main, err := btcutil.NewAddressPubKey([]byte{ + 0x03, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, + 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, + 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, + 0xb1, 0x6e, 0x65}, btcwire.MainNet) + if err != nil { + t.Errorf("Unable to create pubkey address (compressed 2): %v", + err) + return + } + + p2pkUncompressedMain, err := btcutil.NewAddressPubKey([]byte{ + 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, 0x6b, + 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 0xb6, 0x8a, 0x38, + 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 0xd7, 0xb1, 0x48, 0xa6, + 0x90, 0x9a, 0x5c, 0xb2, 0xe0, 0xea, 0xdd, 0xfb, 0x84, 0xcc, + 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, + 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, + 0xf6, 0x56, 0xb4, 0x12, 0xa3}, btcwire.MainNet) + if err != nil { + t.Errorf("Unable to create pubkey address (uncompressed): %v", + err) + return + } + tests := []struct { in btcutil.Address expected []byte @@ -2911,10 +2947,54 @@ func TestPayToAddrScript(t *testing.T) { }, nil, }, + // pay-to-pubkey address on mainnet. compressed key. + { + p2pkCompressedMain, + []byte{ + btcscript.OP_DATA_33, + 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, + 0x4c, 0x95, 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, + 0x3d, 0x8d, 0x79, 0x03, 0xc3, 0xeb, 0xec, 0x3a, + 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, 0x52, 0xc6, + 0xb4, btcscript.OP_CHECKSIG, + }, + nil, + }, + // pay-to-pubkey address on mainnet. compressed key (other way). + { + p2pkCompressed2Main, + []byte{ + btcscript.OP_DATA_33, + 0x03, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, + 0x1b, 0xa1, 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, + 0x61, 0xcf, 0x43, 0xe0, 0x01, 0xf9, 0x13, 0x7f, + 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, 0xb1, 0x6e, + 0x65, btcscript.OP_CHECKSIG, + }, + nil, + }, + // pay-to-pubkey address on mainnet. uncompressed key. + { + p2pkUncompressedMain, + []byte{ + btcscript.OP_DATA_65, + 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, + 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, + 0x1e, 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, + 0x2e, 0xca, 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, + 0x5c, 0xb2, 0xe0, 0xea, 0xdd, 0xfb, 0x84, 0xcc, + 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, + 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, + 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, + 0xa3, btcscript.OP_CHECKSIG, + }, + nil, + }, // Supported address types with nil pointers. {(*btcutil.AddressPubKeyHash)(nil), []byte{}, btcscript.ErrUnsupportedAddress}, {(*btcutil.AddressScriptHash)(nil), []byte{}, btcscript.ErrUnsupportedAddress}, + {(*btcutil.AddressPubKey)(nil), []byte{}, btcscript.ErrUnsupportedAddress}, // Unsupported address type. {&bogusAddress{}, []byte{}, btcscript.ErrUnsupportedAddress}, diff --git a/test_coverage.txt b/test_coverage.txt index c6000c10..c74cda29 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -9,13 +9,14 @@ github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23) github.com/conformal/btcscript/stack.go asInt 100.00% (21/21) github.com/conformal/btcscript/script.go NewScript 100.00% (21/21) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (16/16) -github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (15/15) github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (15/15) +github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (15/15) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) github.com/conformal/btcscript/script.go Script.CheckErrorCondition 100.00% (11/11) +github.com/conformal/btcscript/script.go PayToAddrScript 100.00% (11/11) github.com/conformal/btcscript/script.go typeOfScript 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) @@ -31,139 +32,139 @@ github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) +github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) -github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) -github.com/conformal/btcscript/script.go Script.Execute 100.00% (8/8) -github.com/conformal/btcscript/script.go PayToAddrScript 100.00% (8/8) -github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) +github.com/conformal/btcscript/script.go Script.Execute 100.00% (8/8) +github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddInt64 100.00% (7/7) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddUint64 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddInt64 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) -github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddUint64 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) +github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) -github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) +github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) -github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) -github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) -github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) -github.com/conformal/btcscript/script.go isNullData 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) -github.com/conformal/btcscript/script.go setStack 100.00% (3/3) -github.com/conformal/btcscript/script.go asSmallInt 100.00% (3/3) +github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) +github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/script.go isNullData 100.00% (4/4) +github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) +github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) +github.com/conformal/btcscript/script.go ScriptClass.String 100.00% (3/3) github.com/conformal/btcscript/script.go isSmallInt 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) +github.com/conformal/btcscript/script.go asSmallInt 100.00% (3/3) github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) -github.com/conformal/btcscript/script.go ScriptClass.String 100.00% (3/3) +github.com/conformal/btcscript/script.go setStack 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) -github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) -github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddOp 100.00% (2/2) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Reset 100.00% (2/2) -github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) -github.com/conformal/btcscript/log.go init 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) +github.com/conformal/btcscript/log.go init 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go init 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) github.com/conformal/btcscript/script.go payToPubKeyHashScript 100.00% (1/1) github.com/conformal/btcscript/script.go payToScriptHashScript 100.00% (1/1) -github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) +github.com/conformal/btcscript/script.go payToPubKeyScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go init 100.00% (1/1) github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) github.com/conformal/btcscript/scriptbuilder.go NewScriptBuilder 100.00% (1/1) github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckSig 93.10% (27/29) github.com/conformal/btcscript/script.go unparseScript 85.71% (6/7) github.com/conformal/btcscript/script.go expectedInputs 85.71% (6/7) github.com/conformal/btcscript/script.go calcScriptHash 82.05% (32/39) -github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) github.com/conformal/btcscript/script.go IsPushOnlyScript 75.00% (3/4) +github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) github.com/conformal/btcscript/script.go HasCanonicalPushes 66.67% (12/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/10) github.com/conformal/btcscript/script.go CalcMultiSigStats 0.00% (0/8) github.com/conformal/btcscript/script.go @540:34 0.00% (0/6) github.com/conformal/btcscript/script.go @528:34 0.00% (0/4) github.com/conformal/btcscript/script.go @573:34 0.00% (0/3) -github.com/conformal/btcscript/log.go UseLogger 0.00% (0/1) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) github.com/conformal/btcscript/opcode.go @1741:33 0.00% (0/1) -github.com/conformal/btcscript --------------------------- 95.14% (1037/1090) +github.com/conformal/btcscript/log.go UseLogger 0.00% (0/1) +github.com/conformal/btcscript --------------------------- 95.16% (1041/1094) From 88f3c73ad1c2501386cf90942d6c1ea5e3727870 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Fri, 21 Feb 2014 00:20:24 +0000 Subject: [PATCH 101/174] Add MultiSigScript to provide a canonical script for a multisig transaction. --- script.go | 23 +++++++ script_test.go | 148 +++++++++++++++++++++++++++++++++++++++++++ scriptbuilder.go | 3 +- test_coverage.txt | 157 +++++++++++++++++++++++----------------------- 4 files changed, 252 insertions(+), 79 deletions(-) diff --git a/script.go b/script.go index 0ab0b36d..469a7962 100644 --- a/script.go +++ b/script.go @@ -1050,6 +1050,29 @@ func PayToAddrScript(addr btcutil.Address) ([]byte, error) { return nil, ErrUnsupportedAddress } +// ErrBadNumRequired is returned from MultiSigScript when nrequired is larger +// than the number of provided public keys. +var ErrBadNumRequired = errors.New("more signatures required than keys present") + +// MultiSigScript returns a valid script for a multisignature redemption where +// nrequired of the keys in pubkeys are required to have signed the transaction +// for success. An ErrBadNumRequired will be returned if nrequired is larger than +// the number of keys provided. +func MultiSigScript(pubkeys []*btcutil.AddressPubKey, nrequired int) ([]byte, error) { + if len(pubkeys) < nrequired { + return nil, ErrBadNumRequired + } + + builder := NewScriptBuilder().AddInt64(int64(nrequired)) + for _, key := range pubkeys { + builder.AddData(key.ScriptAddress()) + } + builder.AddInt64(int64(len(pubkeys))) + builder.AddOp(OP_CHECKMULTISIG) + + return builder.Script(), nil +} + // SignatureScript creates an input signature script for tx to spend // BTC sent from a previous output to the owner of privkey. tx must // include all transaction inputs and outputs, however txin scripts are diff --git a/script_test.go b/script_test.go index 003818a8..0b59070c 100644 --- a/script_test.go +++ b/script_test.go @@ -3016,3 +3016,151 @@ func TestPayToAddrScript(t *testing.T) { } } } + +func TestMultiSigScript(t *testing.T) { + // mainnet p2pk 13CG6SJ3yHUXo4Cr2RY4THLLJrNFuG3gUg + p2pkCompressedMain, err := btcutil.NewAddressPubKey([]byte{ + 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94 , 0x34, 0x4c, 0x95, + 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d , 0x8d, 0x79, 0x03, + 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24 , 0x89, 0x5d, 0xca, + 0x52, 0xc6, 0xb4}, btcwire.MainNet) + if err != nil { + t.Errorf("Unable to create pubkey address (compressed): %v", + err) + return + } + p2pkCompressed2Main, err := btcutil.NewAddressPubKey([]byte{ + 0x03, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, + 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, + 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, + 0xb1, 0x6e, 0x65}, btcwire.MainNet) + if err != nil { + t.Errorf("Unable to create pubkey address (compressed 2): %v", + err) + return + } + + p2pkUncompressedMain, err := btcutil.NewAddressPubKey([]byte{ + 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, 0x6b, + 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 0xb6, 0x8a, 0x38, + 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 0xd7, 0xb1, 0x48, 0xa6, + 0x90, 0x9a, 0x5c, 0xb2, 0xe0, 0xea, 0xdd, 0xfb, 0x84, 0xcc, + 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, + 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, + 0xf6, 0x56, 0xb4, 0x12, 0xa3}, btcwire.MainNet) + if err != nil { + t.Errorf("Unable to create pubkey address (uncompressed): %v", + err) + return + } + + tests := []struct { + keys []*btcutil.AddressPubKey + nrequired int + expected []byte + err error + }{ + { + []*btcutil.AddressPubKey{ + p2pkCompressedMain, + p2pkCompressed2Main, + }, + 1, + []byte{ + btcscript.OP_1, + btcscript.OP_DATA_33, + 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, + 0x4c, 0x95, 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, + 0x3d, 0x8d, 0x79, 0x03, 0xc3, 0xeb, 0xec, 0x3a, + 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, 0x52, 0xc6, + 0xb4, + btcscript.OP_DATA_33, + 0x03, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, + 0x1b, 0xa1, 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, + 0x61, 0xcf, 0x43, 0xe0, 0x01, 0xf9, 0x13, 0x7f, + 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, 0xb1, 0x6e, + 0x65, + btcscript.OP_2, btcscript.OP_CHECKMULTISIG, + }, + nil, + }, + { + []*btcutil.AddressPubKey{ + p2pkCompressedMain, + p2pkCompressed2Main, + }, + 2, + []byte{ + btcscript.OP_2, + btcscript.OP_DATA_33, + 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, + 0x4c, 0x95, 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, + 0x3d, 0x8d, 0x79, 0x03, 0xc3, 0xeb, 0xec, 0x3a, + 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, 0x52, 0xc6, + 0xb4, + btcscript.OP_DATA_33, + 0x03, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, + 0x1b, 0xa1, 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, + 0x61, 0xcf, 0x43, 0xe0, 0x01, 0xf9, 0x13, 0x7f, + 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, 0xb1, 0x6e, + 0x65, + btcscript.OP_2, btcscript.OP_CHECKMULTISIG, + }, + nil, + }, + { + []*btcutil.AddressPubKey{ + p2pkCompressedMain, + p2pkCompressed2Main, + }, + 3, + []byte{}, + btcscript.ErrBadNumRequired, + }, + { + []*btcutil.AddressPubKey{ + p2pkUncompressedMain, + }, + 1, + []byte{ + btcscript.OP_1, btcscript.OP_DATA_65, + 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, + 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, + 0x1e, 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, + 0x2e, 0xca, 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, + 0x5c, 0xb2, 0xe0, 0xea, 0xdd, 0xfb, 0x84, 0xcc, + 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, + 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, + 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, + 0xa3, + btcscript.OP_1, btcscript.OP_CHECKMULTISIG, + }, + nil, + }, + { + []*btcutil.AddressPubKey{ + p2pkUncompressedMain, + }, + 2, + []byte{}, + btcscript.ErrBadNumRequired, + }, + } + + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + script, err := btcscript.MultiSigScript(test.keys, + test.nrequired) + if err != test.err { + t.Errorf("MultiSigScript #%d unexpected error - "+ + "got %v, want %v", i, err, test.err) + continue + } + + if !bytes.Equal(script, test.expected) { + t.Errorf("MultiSigScript #%d got: %x\nwant: %x", + i, script, test.expected) + continue + } + } +} diff --git a/scriptbuilder.go b/scriptbuilder.go index b623dde3..c20a0446 100644 --- a/scriptbuilder.go +++ b/scriptbuilder.go @@ -23,7 +23,8 @@ const ( // does not ensure the script will execute correctly. // // For example, the following would build a 2-of-3 multisig script for usage in -// a pay-to-script-hash: +// a pay-to-script-hash (although in this situation MultiSigScript() would be a +// better choice to generate the script): // builder := btcscript.NewScriptBuilder() // builder.AddOp(btcscript.OP_2).AddData(pubKey1).AddData(pubKey2) // builder.AddData(pubKey3).AddOp(btcscript.OP_3) diff --git a/test_coverage.txt b/test_coverage.txt index c74cda29..5e3c2c9d 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -9,148 +9,149 @@ github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23) github.com/conformal/btcscript/stack.go asInt 100.00% (21/21) github.com/conformal/btcscript/script.go NewScript 100.00% (21/21) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (16/16) -github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (15/15) github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (15/15) +github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (15/15) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) +github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) -github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) -github.com/conformal/btcscript/script.go Script.CheckErrorCondition 100.00% (11/11) github.com/conformal/btcscript/script.go PayToAddrScript 100.00% (11/11) -github.com/conformal/btcscript/script.go typeOfScript 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) +github.com/conformal/btcscript/script.go Script.CheckErrorCondition 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) +github.com/conformal/btcscript/script.go typeOfScript 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) -github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) -github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) -github.com/conformal/btcscript/script.go Script.Execute 100.00% (8/8) -github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) +github.com/conformal/btcscript/script.go Script.Execute 100.00% (8/8) +github.com/conformal/btcscript/script.go MultiSigScript 100.00% (8/8) +github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddInt64 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddInt64 100.00% (7/7) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddUint64 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) -github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) +github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (4/4) github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) github.com/conformal/btcscript/script.go isNullData 100.00% (4/4) -github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) +github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) github.com/conformal/btcscript/script.go ScriptClass.String 100.00% (3/3) github.com/conformal/btcscript/script.go isSmallInt 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) github.com/conformal/btcscript/script.go asSmallInt 100.00% (3/3) github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) github.com/conformal/btcscript/script.go setStack 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) -github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) -github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddOp 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Reset 100.00% (2/2) -github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) -github.com/conformal/btcscript/log.go init 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) -github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) -github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) +github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) +github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) +github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) +github.com/conformal/btcscript/log.go init 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) github.com/conformal/btcscript/script.go payToPubKeyHashScript 100.00% (1/1) github.com/conformal/btcscript/script.go payToScriptHashScript 100.00% (1/1) github.com/conformal/btcscript/script.go payToPubKeyScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go init 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) -github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) github.com/conformal/btcscript/scriptbuilder.go NewScriptBuilder 100.00% (1/1) -github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) +github.com/conformal/btcscript/opcode.go init 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckSig 93.10% (27/29) github.com/conformal/btcscript/script.go unparseScript 85.71% (6/7) github.com/conformal/btcscript/script.go expectedInputs 85.71% (6/7) @@ -166,5 +167,5 @@ github.com/conformal/btcscript/script.go @573:34 0.00% (0/3) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) github.com/conformal/btcscript/opcode.go @1741:33 0.00% (0/1) github.com/conformal/btcscript/log.go UseLogger 0.00% (0/1) -github.com/conformal/btcscript --------------------------- 95.16% (1041/1094) +github.com/conformal/btcscript --------------------------- 95.19% (1049/1102) From 982f282e10ad7116448280c6d5c45084949d22a3 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 21 Feb 2014 02:09:55 -0600 Subject: [PATCH 102/174] Go fmt. --- script.go | 8 ++++---- script_test.go | 20 ++++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/script.go b/script.go index 469a7962..da897bb9 100644 --- a/script.go +++ b/script.go @@ -1014,14 +1014,14 @@ func payToPubKeyHashScript(pubKeyHash []byte) []byte { // script hash. It is expected that the input is a valid hash. func payToScriptHashScript(scriptHash []byte) []byte { return NewScriptBuilder().AddOp(OP_HASH160).AddData(scriptHash). - AddOp(OP_EQUAL).Script() + AddOp(OP_EQUAL).Script() } // payToPubkeyScript creates a new script to pay a transaction output to a // public key. It is expected that the input is a valid pubkey. func payToPubKeyScript(serializedPubKey []byte) []byte { return NewScriptBuilder().AddData(serializedPubKey). - AddOp(OP_CHECKSIG).Script() + AddOp(OP_CHECKSIG).Script() } // PayToAddrScript creates a new script to pay a transaction output to a the @@ -1052,7 +1052,7 @@ func PayToAddrScript(addr btcutil.Address) ([]byte, error) { // ErrBadNumRequired is returned from MultiSigScript when nrequired is larger // than the number of provided public keys. -var ErrBadNumRequired = errors.New("more signatures required than keys present") +var ErrBadNumRequired = errors.New("more signatures required than keys present") // MultiSigScript returns a valid script for a multisignature redemption where // nrequired of the keys in pubkeys are required to have signed the transaction @@ -1064,7 +1064,7 @@ func MultiSigScript(pubkeys []*btcutil.AddressPubKey, nrequired int) ([]byte, er } builder := NewScriptBuilder().AddInt64(int64(nrequired)) - for _, key := range pubkeys { + for _, key := range pubkeys { builder.AddData(key.ScriptAddress()) } builder.AddInt64(int64(len(pubkeys))) diff --git a/script_test.go b/script_test.go index 0b59070c..337a2f04 100644 --- a/script_test.go +++ b/script_test.go @@ -2887,9 +2887,9 @@ func TestPayToAddrScript(t *testing.T) { // mainnet p2pk 13CG6SJ3yHUXo4Cr2RY4THLLJrNFuG3gUg p2pkCompressedMain, err := btcutil.NewAddressPubKey([]byte{ - 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94 , 0x34, 0x4c, 0x95, - 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d , 0x8d, 0x79, 0x03, - 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24 , 0x89, 0x5d, 0xca, + 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, + 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, + 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, 0x52, 0xc6, 0xb4}, btcwire.MainNet) if err != nil { t.Errorf("Unable to create pubkey address (compressed): %v", @@ -3020,9 +3020,9 @@ func TestPayToAddrScript(t *testing.T) { func TestMultiSigScript(t *testing.T) { // mainnet p2pk 13CG6SJ3yHUXo4Cr2RY4THLLJrNFuG3gUg p2pkCompressedMain, err := btcutil.NewAddressPubKey([]byte{ - 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94 , 0x34, 0x4c, 0x95, - 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d , 0x8d, 0x79, 0x03, - 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24 , 0x89, 0x5d, 0xca, + 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, + 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, + 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, 0x52, 0xc6, 0xb4}, btcwire.MainNet) if err != nil { t.Errorf("Unable to create pubkey address (compressed): %v", @@ -3055,10 +3055,10 @@ func TestMultiSigScript(t *testing.T) { } tests := []struct { - keys []*btcutil.AddressPubKey - nrequired int - expected []byte - err error + keys []*btcutil.AddressPubKey + nrequired int + expected []byte + err error }{ { []*btcutil.AddressPubKey{ From da1fcc6dbd71fd14de90e77ce77895f26383c10f Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 21 Feb 2014 02:11:11 -0600 Subject: [PATCH 103/174] Tighten the check for pay-to-pubkey scripts. This commit tightens the check for a pay-to-pubkey script by ensuring the length of the pubkey is one of the two valid values of 33 or 65. This mirrors the checks in the multisig script type check as well. ok @owainga --- script.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/script.go b/script.go index da897bb9..2177df94 100644 --- a/script.go +++ b/script.go @@ -204,9 +204,9 @@ func isSmallInt(op *opcode) bool { // isPubkey returns true if the script passed is a pubkey transaction, false // otherwise. func isPubkey(pops []parsedOpcode) bool { + // valid pubkeys are either 33 or 65 bytes return len(pops) == 2 && - pops[0].opcode.value > OP_FALSE && - pops[0].opcode.value <= OP_DATA_75 && + (len(pops[0].data) == 33 || len(pops[0].data) == 65) && pops[1].opcode.value == OP_CHECKSIG } From 201d6651c983565947abf35f1af108ed98d06809 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Thu, 13 Mar 2014 17:20:45 +0000 Subject: [PATCH 104/174] Fix tests after IsForNet addition to btcutil.Address interface. dhill pointed this out to me. --- script_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/script_test.go b/script_test.go index 337a2f04..d1eb604e 100644 --- a/script_test.go +++ b/script_test.go @@ -2863,6 +2863,11 @@ func (b *bogusAddress) ScriptAddress() []byte { return []byte{} } +// IsForNet lies blatantly to satisfy the btcutil.Address interface. +func (b *bogusAddress) IsForNet(btcwire.BitcoinNet) bool { + return true // why not? +} + func TestPayToAddrScript(t *testing.T) { // 1MirQ9bwyQcGVJPwKUgapu5ouK2E2Ey4gX p2pkhMain, err := btcutil.NewAddressPubKeyHash([]byte{ From 8df0af32d605fb56350ab8d989eeab08a4c992d7 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Fri, 14 Mar 2014 14:48:19 +0000 Subject: [PATCH 105/174] Encountering OP_VERIF and OP_VERNOTIF in execution is always an error. I honestly thought we already handled this, but some tests dhill is working on shows that we didn't. --- opcode.go | 16 ++++++++++++++++ script.go | 9 ++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/opcode.go b/opcode.go index 710cd212..3b26b329 100644 --- a/opcode.go +++ b/opcode.go @@ -862,6 +862,22 @@ type parsedOpcode struct { opfunc func(op parsedOpcode, s Script) error } +// The following opcodes are always illegal when passed over by the program +// counter even if in a non-executed branch. (it isn't a coincidence that they +// are conditionals). +func (pop *parsedOpcode) alwaysIllegal() bool { + switch pop.opcode.value { + case OP_VERIF: + return true + case OP_VERNOTIF: + return true + default: + return false + } +} + +// The following opcode are conditional and thus change the conditional +// execution stack state when passed. func (pop *parsedOpcode) conditional() bool { switch pop.opcode.value { case OP_IF: diff --git a/script.go b/script.go index 2177df94..3fe74c3a 100644 --- a/script.go +++ b/script.go @@ -52,6 +52,11 @@ var ( // is encountered. StackErrReservedOpcode = errors.New("Reserved Opcode") + // StackErrAlwaysIllegal is returned when an opcode marked as always + // illegal is encountered. Currently this is just OP_VERIF and + // OP_VERNOTIF. + StackErrAlwaysIllegal = errors.New("Always Illlegal instruction encountered") + // StackErrEarlyReturn is returned when OP_RETURN is executed in the // script. StackErrEarlyReturn = errors.New("Script returned early") @@ -602,7 +607,9 @@ func (m *Script) Step() (done bool, err error) { if m.condStack[0] != OpCondTrue { // some opcodes still 'activate' if on the non-executing side // of conditional execution - if opcode.conditional() { + if opcode.alwaysIllegal() { + return true, StackErrAlwaysIllegal + } else if opcode.conditional() { executeInstr = true } else { executeInstr = false From c1a6e47f38f2847b1cac108fd88252670b42e94c Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Fri, 14 Mar 2014 14:52:22 +0000 Subject: [PATCH 106/174] Conditionals must not straddle two scripts. Found by tests dhill is working on. We checked that ifs were closed at the end of execution but not at script switching time, we now move this to just after finishing a single script. --- script.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/script.go b/script.go index 3fe74c3a..23e1fdf5 100644 --- a/script.go +++ b/script.go @@ -583,10 +583,6 @@ func (s *Script) CheckErrorCondition() (err error) { })) err = StackErrScriptFailed } - if err == nil && len(s.condStack) != 1 { - // conditional execution stack context left active - err = StackErrMissingEndif - } return err } @@ -625,6 +621,11 @@ func (m *Script) Step() (done bool, err error) { // prepare for next instruction m.scriptoff++ if m.scriptoff >= len(m.scripts[m.scriptidx]) { + // Illegal to have an `if' that straddles two scripts. + if err == nil && len(m.condStack) != 1 { + return false, StackErrMissingEndif + } + m.numOps = 0 // number of ops is per script. m.scriptoff = 0 if m.scriptidx == 0 && m.bip16 { From a5e7e9ebb669e09f2abb0783c635f4d340b11ff4 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Fri, 14 Mar 2014 17:20:51 +0000 Subject: [PATCH 107/174] Disabled opcodes are `fail if pc passes' not fail if execute. Detected by bitcoind negative tests. --- opcode.go | 39 +++++++++++++++++++++++++++++++++++++++ script.go | 4 +++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/opcode.go b/opcode.go index 3b26b329..58ec7367 100644 --- a/opcode.go +++ b/opcode.go @@ -862,6 +862,45 @@ type parsedOpcode struct { opfunc func(op parsedOpcode, s Script) error } +// The following opcodes are disabled and are thus always bad to see in the +// instruction stream (even if turned off by a conditional). +func (pop *parsedOpcode) disabled() bool { + switch pop.opcode.value { + case OP_CAT: + return true + case OP_SUBSTR: + return true + case OP_LEFT: + return true + case OP_RIGHT: + return true + case OP_INVERT: + return true + case OP_AND: + return true + case OP_OR: + return true + case OP_XOR: + return true + case OP_2MUL: + return true + case OP_2DIV: + return true + case OP_MUL: + return true + case OP_DIV: + return true + case OP_MOD: + return true + case OP_LSHIFT: + return true + case OP_RSHIFT: + return true + default: + return false + } +} + // The following opcodes are always illegal when passed over by the program // counter even if in a non-executed branch. (it isn't a coincidence that they // are conditionals). diff --git a/script.go b/script.go index 23e1fdf5..528969bc 100644 --- a/script.go +++ b/script.go @@ -603,7 +603,9 @@ func (m *Script) Step() (done bool, err error) { if m.condStack[0] != OpCondTrue { // some opcodes still 'activate' if on the non-executing side // of conditional execution - if opcode.alwaysIllegal() { + if opcode.disabled() { + return true, StackErrOpDisabled + } else if opcode.alwaysIllegal() { return true, StackErrAlwaysIllegal } else if opcode.conditional() { executeInstr = true From c7d5102954bdfaf60b198281f12b9423df8fd5cb Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Fri, 14 Mar 2014 17:22:57 +0000 Subject: [PATCH 108/174] Alt stack should be purged between scripts. Found by bitcoind negative scripts. --- script.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/script.go b/script.go index 528969bc..f750858a 100644 --- a/script.go +++ b/script.go @@ -628,6 +628,9 @@ func (m *Script) Step() (done bool, err error) { return false, StackErrMissingEndif } + // alt stack doesn't persist. + _ = m.astack.DropN(m.astack.Depth()) + m.numOps = 0 // number of ops is per script. m.scriptoff = 0 if m.scriptidx == 0 && m.bip16 { From f80c3255a34cea396f9bc6bec273c71505aa0616 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Fri, 14 Mar 2014 17:51:17 +0000 Subject: [PATCH 109/174] PopInt now guarantees that number will be 32 bit. So remove later checks that need this. --- opcode.go | 19 ++++--------------- opcode_test.go | 5 +++-- stack.go | 14 +++++++++----- 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/opcode.go b/opcode.go index 58ec7367..52b930b9 100644 --- a/opcode.go +++ b/opcode.go @@ -1258,10 +1258,7 @@ func opcodePick(op *parsedOpcode, s *Script) error { return err } - if pidx.BitLen() > 32 { - return StackErrNumberTooBig - } - + // PopInt promises that the int returned is 32 bit. val := int(pidx.Int64()) return s.dstack.PickN(val) @@ -1275,10 +1272,7 @@ func opcodeRoll(op *parsedOpcode, s *Script) error { return err } - if ridx.BitLen() > 32 { - return StackErrNumberTooBig - } - + // PopInt promises that the int returned is 32 bit. val := int(ridx.Int64()) return s.dstack.RollN(val) @@ -1823,10 +1817,7 @@ func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error { // XXX arbitrary limits // nore more than 20 pubkeyhs, or 201 operations - if numPubkeys.BitLen() > 32 { - return StackErrNumberTooBig - } - + // PopInt promises that the int returned is 32 bit. npk := int(numPubkeys.Int64()) if npk < 0 || npk > MaxPubKeysPerMultiSig { return StackErrTooManyPubkeys @@ -1848,10 +1839,8 @@ func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error { if err != nil { return err } - if numSignatures.BitLen() > 32 { - return StackErrNumberTooBig - } + // PopInt promises that the int returned is 32 bit. nsig := int(numSignatures.Int64()) sigStrings := make([][]byte, nsig) diff --git a/opcode_test.go b/opcode_test.go index d5591df1..2549973c 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -872,12 +872,13 @@ var detailedTests = []detailedTest{ disassembly: "OP_IFDUP", }, { - name: "toaltastack", + // alt stack is purged at the end of execution + name: "toaltstack", before: [][]byte{{1}}, altbefore: [][]byte{}, script: []byte{btcscript.OP_TOALTSTACK}, after: [][]byte{}, - altafter: [][]byte{{1}}, + altafter: [][]byte{}, disassembly: "OP_TOALTSTACK", }, { diff --git a/stack.go b/stack.go index ffc30429..f2c96c5f 100644 --- a/stack.go +++ b/stack.go @@ -10,9 +10,13 @@ import ( // asInt converts a byte array to a bignum by treating it as a little endian // number with sign bit. -func asInt(v []byte) *big.Int { +func asInt(v []byte) (*big.Int, error) { + // Only 32bit numbers allowed. + if len(v) > 4 { + return nil, StackErrNumberTooBig + } if len(v) == 0 { - return big.NewInt(0) + return big.NewInt(0), nil } negative := false origlen := len(v) @@ -44,7 +48,7 @@ func asInt(v []byte) *big.Int { if negative { num = num.Neg(num) } - return num + return num, nil } // fromInt provies a Big.Int in little endian format with the high bit of the @@ -127,7 +131,7 @@ func (s *Stack) PopInt() (*big.Int, error) { if err != nil { return nil, err } - return asInt(so), nil + return asInt(so) } // PopBool pops the value off the top of the stack, converts it into a bool and @@ -155,7 +159,7 @@ func (s *Stack) PeekInt(idx int) (i *big.Int, err error) { if err != nil { return nil, err } - return asInt(so), nil + return asInt(so) } // PeekBool returns the nth item on the stack as a bool without removing it. From 8beb0dec54550f434561e09b1bd9087c2633d2df Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Fri, 14 Mar 2014 18:27:01 +0000 Subject: [PATCH 110/174] Make opcode.Exec run a bunch of unconditional checks Add push length and number of operations to this to match bitcoind behaviour. found that we differed here by their negative tests. --- opcode.go | 31 ++++++++++++++++++++++--------- script.go | 28 ++++++---------------------- 2 files changed, 28 insertions(+), 31 deletions(-) diff --git a/opcode.go b/opcode.go index 52b930b9..c9c1747f 100644 --- a/opcode.go +++ b/opcode.go @@ -932,17 +932,35 @@ func (pop *parsedOpcode) conditional() bool { } } +// exec peforms execution on the opcode. It takes into account whether or not +// it is hidden by conditionals, but some rules still must be tested in this +// case. func (pop *parsedOpcode) exec(s *Script) error { - // *sigh* bitcoind pretty much mandates that we violate layering here. - // Any opcode that isn't just adding data to the stack counts here - // as an operation. Note that OP_RESERVED is less than OP_16 and thus - // is counted as a push opcode here. + // Disabled opcodes are ``fail on program counter''. + if pop.disabled() { + return StackErrOpDisabled + } + + // Always-illegal opcodes are ``fail on program counter''. + if pop.alwaysIllegal() { + return StackErrAlwaysIllegal + } + + // Note that this includes OP_RESERVED which counts as a push operation. if pop.opcode.value > OP_16 { s.numOps++ if s.numOps > MaxOpsPerScript { return StackErrTooManyOperations } + } else if len(pop.data) > MaxScriptElementSize { + return StackErrElementTooBig + } + + // If we are not a conditional opcode and we aren't executing, then + // we are done now. + if s.condStack[0] != OpCondTrue && !pop.conditional() { + return nil } return pop.opcode.opfunc(pop, s) } @@ -1050,11 +1068,6 @@ func opcodeFalse(op *parsedOpcode, s *Script) error { } func opcodePushData(op *parsedOpcode, s *Script) error { - // This max script element test must occur at execution time instead - // of parse time to match bitcoind behaviour. - if len(op.data) > MaxScriptElementSize { - return StackErrElementTooBig - } s.dstack.PushByteArray(op.data) return nil } diff --git a/script.go b/script.go index f750858a..8f72339a 100644 --- a/script.go +++ b/script.go @@ -595,29 +595,13 @@ func (m *Script) Step() (done bool, err error) { // verify that it is pointing to a valid script address err = m.validPC() if err != nil { - return + return true, err } opcode := m.scripts[m.scriptidx][m.scriptoff] - executeInstr := true - if m.condStack[0] != OpCondTrue { - // some opcodes still 'activate' if on the non-executing side - // of conditional execution - if opcode.disabled() { - return true, StackErrOpDisabled - } else if opcode.alwaysIllegal() { - return true, StackErrAlwaysIllegal - } else if opcode.conditional() { - executeInstr = true - } else { - executeInstr = false - } - } - if executeInstr { - err = opcode.exec(m) - if err != nil { - return - } + err = opcode.exec(m) + if err != nil { + return true, err } // prepare for next instruction @@ -664,10 +648,10 @@ func (m *Script) Step() (done bool, err error) { } m.lastcodesep = 0 if m.scriptidx >= len(m.scripts) { - done = true + return true, nil } } - return + return false, nil } // curPC returns either the current script and offset, or an error if the From d6d755e411cadfcff143210741803f63da1a53bf Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Fri, 14 Mar 2014 18:35:13 +0000 Subject: [PATCH 111/174] Always return reserved opcode for always-illegal ops. --- opcode.go | 2 +- script.go | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/opcode.go b/opcode.go index c9c1747f..b89c84b9 100644 --- a/opcode.go +++ b/opcode.go @@ -943,7 +943,7 @@ func (pop *parsedOpcode) exec(s *Script) error { // Always-illegal opcodes are ``fail on program counter''. if pop.alwaysIllegal() { - return StackErrAlwaysIllegal + return StackErrReservedOpcode } // Note that this includes OP_RESERVED which counts as a push operation. diff --git a/script.go b/script.go index 8f72339a..30575337 100644 --- a/script.go +++ b/script.go @@ -52,11 +52,6 @@ var ( // is encountered. StackErrReservedOpcode = errors.New("Reserved Opcode") - // StackErrAlwaysIllegal is returned when an opcode marked as always - // illegal is encountered. Currently this is just OP_VERIF and - // OP_VERNOTIF. - StackErrAlwaysIllegal = errors.New("Always Illlegal instruction encountered") - // StackErrEarlyReturn is returned when OP_RETURN is executed in the // script. StackErrEarlyReturn = errors.New("Script returned early") From dec16d7ff26f5145a0e573ddbd87df4108d104a8 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Fri, 14 Mar 2014 18:35:36 +0000 Subject: [PATCH 112/174] Enforce a combined max stack depth of 1000 after every opcode. This limit is for the sum of main and alt stacks. Found by bitcoind negative tests. --- script.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/script.go b/script.go index 30575337..a3819b01 100644 --- a/script.go +++ b/script.go @@ -116,8 +116,16 @@ var ( // StackErrNonPushOnly is returned when ScriptInfo is called with a // pkScript that peforms operations other that pushing data to the stack. StackErrNonPushOnly = errors.New("SigScript is non pushonly") + + // StackErrOverflow is returned when stack and altstack combined depth + // is over the limit. + StackErrOverflow = errors.New("Stacks overflowed") ) +// maxStackSize is the maximum combined height of stack and alt stack during +// execution. +const maxStackSize = 1000 + // ErrUnsupportedAddress is returned when a concrete type that implements // a btcutil.Address is not a supported type. var ErrUnsupportedAddress = errors.New("unsupported address type") @@ -599,6 +607,10 @@ func (m *Script) Step() (done bool, err error) { return true, err } + if m.dstack.Depth() + m.astack.Depth() > maxStackSize { + return false, StackErrOverflow + } + // prepare for next instruction m.scriptoff++ if m.scriptoff >= len(m.scripts[m.scriptidx]) { From 42f6576b02636de92e44e206421ca4d0c622996b Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Fri, 14 Mar 2014 18:40:35 +0000 Subject: [PATCH 113/174] Enforce max script length of 10000. Detected by bitcoind negative script tests. Note that this length is only for *executing* scripts, this is why it is in NewScript. --- script.go | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/script.go b/script.go index a3819b01..9fa4a68d 100644 --- a/script.go +++ b/script.go @@ -24,6 +24,10 @@ var ( // too long for the length of the script. StackErrShortScript = errors.New("execute past end of script") + // StackErrLongScript is returned if the script has an opcode that is + // too long for the length of the script. + StackErrLongScript = errors.New("script is longer than maximum allowed") + // StackErrUnderflow is returned if an opcode requires more items on the // stack than is present. StackErrUnderflow = errors.New("stack underflow") @@ -122,9 +126,14 @@ var ( StackErrOverflow = errors.New("Stacks overflowed") ) -// maxStackSize is the maximum combined height of stack and alt stack during -// execution. -const maxStackSize = 1000 +const ( + // maxStackSize is the maximum combined height of stack and alt stack + // during execution. + maxStackSize = 1000 + + // maxScriptSize is the maximum allowed length of a raw script. + maxScriptSize = 10000 +) // ErrUnsupportedAddress is returned when a concrete type that implements // a btcutil.Address is not a supported type. @@ -492,6 +501,9 @@ func NewScript(scriptSig []byte, scriptPubKey []byte, txidx int, tx *btcwire.Msg scripts := [][]byte{scriptSig, scriptPubKey} m.scripts = make([][]parsedOpcode, len(scripts)) for i, scr := range scripts { + if len(scr) > maxScriptSize { + return nil, StackErrLongScript + } var err error m.scripts[i], err = parseScript(scr) if err != nil { From 299dcc2fad071d33e5492af381f74dfc630363ae Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Fri, 14 Mar 2014 19:22:42 +0000 Subject: [PATCH 114/174] PushDataN with a 0 length is valid, we were too tight here. Found by bitcoind positive tests. (but of course that is noncanonical anyway, it should be OP_0 ;). --- script.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/script.go b/script.go index 9fa4a68d..b102abc6 100644 --- a/script.go +++ b/script.go @@ -864,7 +864,7 @@ func calcScriptHash(script []parsedOpcode, hashType byte, tx *btcwire.MsgTx, idx // scriptUInt8 return the number stored in the first byte of a slice. func scriptUInt8(script []byte) (uint, error) { - if len(script) <= 1 { + if len(script) < 1 { return 0, StackErrShortScript } return uint(script[0]), nil @@ -872,7 +872,7 @@ func scriptUInt8(script []byte) (uint, error) { // scriptUInt16 returns the number stored in the next 2 bytes of a slice. func scriptUInt16(script []byte) (uint, error) { - if len(script) <= 2 { + if len(script) < 2 { return 0, StackErrShortScript } // Yes this is little endian @@ -881,7 +881,7 @@ func scriptUInt16(script []byte) (uint, error) { // scriptUInt32 returns the number stored in the first 4 bytes of a slice. func scriptUInt32(script []byte) (uint, error) { - if len(script) <= 4 { + if len(script) < 4 { return 0, StackErrShortScript } // Yes this is little endian From 02ee7762e45257bcfde2343617649280d7c6af07 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Fri, 14 Mar 2014 20:11:49 +0000 Subject: [PATCH 115/174] AddData([]byte{}) is valid and should push empty to the stack. Doing so is perfectly idiomatic. Fixes the last of the valid bitcoind script tests. (by fixing the script parser :) --- scriptbuilder.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/scriptbuilder.go b/scriptbuilder.go index c20a0446..e34008bb 100644 --- a/scriptbuilder.go +++ b/scriptbuilder.go @@ -41,18 +41,15 @@ func (b *ScriptBuilder) AddOp(opcode byte) *ScriptBuilder { } // AddData pushes the passed data to the end of the script. It automatically -// chooses canonical opcodes depending on the length of the data. +// chooses canonical opcodes depending on the length of the data. A zero length +// buffer will lead to a push of empty data onto the stack. func (b *ScriptBuilder) AddData(data []byte) *ScriptBuilder { - // Don't modify the script at all if no data was passed. dataLen := len(data) - if dataLen == 0 { - return b - } // When the data consists of a single number that can be represented // by one of the "small integer" opcodes, use that opcode instead of // a data push opcode followed by the number. - if dataLen == 1 && data[0] == 0 { + if dataLen == 0 || dataLen == 1 && data[0] == 0 { b.script = append(b.script, OP_0) return b } else if dataLen == 1 && data[0] <= 16 { From 9375c8dc481beab5af9c642f272f1006a71e74b6 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Fri, 14 Mar 2014 20:59:43 +0000 Subject: [PATCH 116/174] move data extraction fof OP_PUSHDATA into main function. This allows us to centralise the error checking to simplify things a bit. --- script.go | 51 ++++------- test_coverage.txt | 219 +++++++++++++++++++++++----------------------- 2 files changed, 124 insertions(+), 146 deletions(-) diff --git a/script.go b/script.go index b102abc6..0854931b 100644 --- a/script.go +++ b/script.go @@ -421,26 +421,32 @@ func parseScriptTemplate(script []byte, opcodemap map[byte]*opcode) ([]parsedOpc pop.data = script[i+1 : i+op.length] i += op.length case op.length < 0: - var err error var l uint off := i + 1 + + if len(script[off:]) < -op.length { + return retScript, StackErrShortScript + } + + // Next -length bytes are little endian length of data. switch op.length { case -1: - l, err = scriptUInt8(script[off:]) + l = uint(script[off]) case -2: - l, err = scriptUInt16(script[off:]) + l = ((uint(script[off+1]) << 8) | + uint(script[off])) case -4: - l, err = scriptUInt32(script[off:]) + l = ((uint(script[off+3]) << 24) | + (uint(script[off+2]) << 16) | + (uint(script[off+1]) << 8) | + uint(script[off])) default: return retScript, fmt.Errorf("invalid opcode length %d", op.length) } - if err != nil { - return nil, err - } - off = i + 1 - op.length // beginning of data + off += -op.length // beginning of data // Disallow entries that do not fit script or were // sign extended. if int(l) > len(script[off:]) || int(l) < 0 { @@ -619,7 +625,7 @@ func (m *Script) Step() (done bool, err error) { return true, err } - if m.dstack.Depth() + m.astack.Depth() > maxStackSize { + if m.dstack.Depth()+m.astack.Depth() > maxStackSize { return false, StackErrOverflow } @@ -862,33 +868,6 @@ func calcScriptHash(script []parsedOpcode, hashType byte, tx *btcwire.MsgTx, idx return btcwire.DoubleSha256(wbuf.Bytes()) } -// scriptUInt8 return the number stored in the first byte of a slice. -func scriptUInt8(script []byte) (uint, error) { - if len(script) < 1 { - return 0, StackErrShortScript - } - return uint(script[0]), nil -} - -// scriptUInt16 returns the number stored in the next 2 bytes of a slice. -func scriptUInt16(script []byte) (uint, error) { - if len(script) < 2 { - return 0, StackErrShortScript - } - // Yes this is little endian - return ((uint(script[1]) << 8) | uint(script[0])), nil -} - -// scriptUInt32 returns the number stored in the first 4 bytes of a slice. -func scriptUInt32(script []byte) (uint, error) { - if len(script) < 4 { - return 0, StackErrShortScript - } - // Yes this is little endian - return ((uint(script[3]) << 24) | (uint(script[2]) << 16) | - (uint(script[1]) << 8) | uint(script[0])), nil -} - // getStack returns the contents of stack as a byte array bottom up func getStack(stack *Stack) [][]byte { array := make([][]byte, stack.Depth()) diff --git a/test_coverage.txt b/test_coverage.txt index 5e3c2c9d..2105107b 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -1,171 +1,170 @@ -github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 100.00% (62/62) -github.com/conformal/btcscript/script.go Script.Step 100.00% (38/38) -github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (30/30) +github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 100.00% (58/58) +github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (29/29) github.com/conformal/btcscript/address.go ExtractPkScriptAddrs 100.00% (27/27) github.com/conformal/btcscript/script.go CalcScriptInfo 100.00% (25/25) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddData 100.00% (24/24) +github.com/conformal/btcscript/stack.go asInt 100.00% (23/23) github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23) -github.com/conformal/btcscript/stack.go asInt 100.00% (21/21) -github.com/conformal/btcscript/script.go NewScript 100.00% (21/21) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddData 100.00% (22/22) +github.com/conformal/btcscript/opcode.go parsedOpcode.disabled 100.00% (17/17) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (16/16) -github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (15/15) github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (15/15) +github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (15/15) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) -github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) -github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) +github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (13/13) github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) -github.com/conformal/btcscript/script.go PayToAddrScript 100.00% (11/11) -github.com/conformal/btcscript/script.go Script.CheckErrorCondition 100.00% (11/11) +github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) +github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) +github.com/conformal/btcscript/script.go PayToAddrScript 100.00% (11/11) github.com/conformal/btcscript/script.go typeOfScript 100.00% (11/11) +github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) -github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) +github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) +github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) +github.com/conformal/btcscript/script.go Script.CheckErrorCondition 100.00% (9/9) github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) -github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) -github.com/conformal/btcscript/script.go Script.Execute 100.00% (8/8) -github.com/conformal/btcscript/script.go MultiSigScript 100.00% (8/8) -github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) +github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/script.go MultiSigScript 100.00% (8/8) +github.com/conformal/btcscript/script.go Script.Execute 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) -github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddInt64 100.00% (7/7) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddUint64 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) +github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddUint64 100.00% (7/7) +github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) -github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodePick 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) -github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/script.go getStack 100.00% (4/4) -github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) -github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (4/4) github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) -github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) +github.com/conformal/btcscript/script.go getStack 100.00% (4/4) github.com/conformal/btcscript/script.go isNullData 100.00% (4/4) -github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) -github.com/conformal/btcscript/script.go ScriptClass.String 100.00% (3/3) -github.com/conformal/btcscript/script.go isSmallInt 100.00% (3/3) -github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) -github.com/conformal/btcscript/script.go asSmallInt 100.00% (3/3) +github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) +github.com/conformal/btcscript/opcode.go parsedOpcode.alwaysIllegal 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) +github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) +github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) +github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) +github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) +github.com/conformal/btcscript/script.go isSmallInt 100.00% (3/3) +github.com/conformal/btcscript/script.go ScriptClass.String 100.00% (3/3) github.com/conformal/btcscript/script.go setStack 100.00% (3/3) -github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) +github.com/conformal/btcscript/script.go asSmallInt 100.00% (3/3) +github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) +github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddOp 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) +github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Reset 100.00% (2/2) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddOp 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) -github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) -github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) -github.com/conformal/btcscript/log.go init 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) -github.com/conformal/btcscript/script.go payToPubKeyHashScript 100.00% (1/1) -github.com/conformal/btcscript/script.go payToScriptHashScript 100.00% (1/1) -github.com/conformal/btcscript/script.go payToPubKeyScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) +github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) +github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) +github.com/conformal/btcscript/log.go init 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) github.com/conformal/btcscript/scriptbuilder.go NewScriptBuilder 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) github.com/conformal/btcscript/opcode.go init 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) +github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) +github.com/conformal/btcscript/script.go payToPubKeyHashScript 100.00% (1/1) +github.com/conformal/btcscript/script.go payToScriptHashScript 100.00% (1/1) +github.com/conformal/btcscript/script.go payToPubKeyScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) +github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.Step 97.30% (36/37) +github.com/conformal/btcscript/script.go NewScript 95.65% (22/23) github.com/conformal/btcscript/opcode.go opcodeCheckSig 93.10% (27/29) -github.com/conformal/btcscript/script.go unparseScript 85.71% (6/7) github.com/conformal/btcscript/script.go expectedInputs 85.71% (6/7) +github.com/conformal/btcscript/script.go unparseScript 85.71% (6/7) github.com/conformal/btcscript/script.go calcScriptHash 82.05% (32/39) -github.com/conformal/btcscript/script.go IsPushOnlyScript 75.00% (3/4) github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) +github.com/conformal/btcscript/script.go IsPushOnlyScript 75.00% (3/4) github.com/conformal/btcscript/script.go HasCanonicalPushes 66.67% (12/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/10) github.com/conformal/btcscript/script.go CalcMultiSigStats 0.00% (0/8) -github.com/conformal/btcscript/script.go @540:34 0.00% (0/6) -github.com/conformal/btcscript/script.go @528:34 0.00% (0/4) -github.com/conformal/btcscript/script.go @573:34 0.00% (0/3) -github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript/opcode.go @1741:33 0.00% (0/1) +github.com/conformal/btcscript/script.go @566:34 0.00% (0/6) +github.com/conformal/btcscript/script.go @554:34 0.00% (0/4) +github.com/conformal/btcscript/script.go @599:34 0.00% (0/3) +github.com/conformal/btcscript/opcode.go opcodeDisabled 0.00% (0/1) github.com/conformal/btcscript/log.go UseLogger 0.00% (0/1) -github.com/conformal/btcscript --------------------------- 95.19% (1049/1102) +github.com/conformal/btcscript/opcode.go @1803:33 0.00% (0/1) +github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) +github.com/conformal/btcscript --------------------------- 94.95% (1054/1110) From c8332cc9a7ecb05812e25a9b3bac565c9656f701 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Sun, 16 Mar 2014 23:07:20 -0500 Subject: [PATCH 117/174] Correct num expected inputs calc for multisig. This commit corrects the number of expected inputs for a multi-sig script to include the additional item that is popped from the stack due to the OP_CHECKMULTISIG consensus bug (which is required and properly performed). Note this issue did NOT affect the consensus critical code and hence would not cause a chain fork. It did however, cause standard p2sh multisig txns to be rejected from the mempool as nonstandard. The tx rejected as non-standard which prompted this was spotted by @mbelshe on IRC. ok @owainga --- script.go | 12 +++++++----- script_test.go | 7 ++++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/script.go b/script.go index 0854931b..11f0dab3 100644 --- a/script.go +++ b/script.go @@ -1128,11 +1128,13 @@ func expectedInputs(pops []parsedOpcode, class ScriptClass) int { return 1 case MultiSigTy: // Standard multisig has a push a small number for the number - // of sigs and number of keys. - // Check the first push instruction to see how many arguments - // are expected. typeOfScript already checked this so we know - // it'll be a small int. - return asSmallInt(pops[0].opcode) + // of sigs and number of keys. Check the first push instruction + // to see how many arguments are expected. typeOfScript already + // checked this so we know it'll be a small int. Also, due to + // the original bitcoind bug where OP_CHECKMULTISIG pops an + // additional item from the stack, add an extra expected input + // for the extra push that is required to compensate. + return asSmallInt(pops[0].opcode) + 1 case NullDataTy: fallthrough default: diff --git a/script_test.go b/script_test.go index d1eb604e..1fb6e7a3 100644 --- a/script_test.go +++ b/script_test.go @@ -1200,7 +1200,7 @@ var txTests = []txTest{ scriptInfo: btcscript.ScriptInfo{ PkScriptClass: btcscript.ScriptHashTy, NumInputs: 2, - ExpectedInputs: 1, + ExpectedInputs: 2, SigOps: 1, }, }, @@ -1780,6 +1780,7 @@ func TestScriptInfo(t *testing.T) { name: "multisig script", sigScript: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_0, // Extra arg for OP_CHECKMULTISIG bug }, pkScript: []byte{ btcscript.OP_3, btcscript.OP_DATA_33, @@ -1802,8 +1803,8 @@ func TestScriptInfo(t *testing.T) { bip16: true, scriptInfo: btcscript.ScriptInfo{ PkScriptClass: btcscript.MultiSigTy, - NumInputs: 3, - ExpectedInputs: 3, + NumInputs: 4, + ExpectedInputs: 4, SigOps: 3, }, }, From dab2a7cb0fec7269d88209736e9a09cf25d5415e Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Mon, 17 Mar 2014 15:05:39 +0000 Subject: [PATCH 118/174] Don't possibly dereference bad signatures in OP_CHECKMULTISIG. We do all the preprocessing in one loop. Fixes a bug introduced a while ago to handle invalid signatures. Found by more tests from bitcoind. --- opcode.go | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/opcode.go b/opcode.go index b89c84b9..cfe78a70 100644 --- a/opcode.go +++ b/opcode.go @@ -1819,6 +1819,11 @@ func opcodeCheckSigVerify(op *parsedOpcode, s *Script) error { return err } +type sig struct { + s *btcec.Signature + ht byte +} + // stack; sigs pubkeys func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error { @@ -1857,21 +1862,25 @@ func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error { nsig := int(numSignatures.Int64()) sigStrings := make([][]byte, nsig) - signatures := make([]*btcec.Signature, 0, nsig) + signatures := make([]sig, 0, nsig) for i := range sigStrings { sigStrings[i], err = s.dstack.PopByteArray() if err != nil { return err } - var sig *btcec.Signature + if len(sigStrings[i]) == 0 { + continue + } + sig := sig{} + sig.ht = sigStrings[i][len(sigStrings[i])-1] // skip off the last byte for hashtype if s.der { - sig, err = + sig.s, err = btcec.ParseDERSignature( sigStrings[i][:len(sigStrings[i])-1], btcec.S256()) } else { - sig, err = + sig.s, err = btcec.ParseSignature( sigStrings[i][:len(sigStrings[i])-1], btcec.S256()) @@ -1906,10 +1915,8 @@ func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error { for i := range signatures { // check signatures. success := false - // get hashtype from original byte string - hashType := sigStrings[i][len(sigStrings[i])-1] - hash := calcScriptHash(script, hashType, &s.tx, s.txidx) + hash := calcScriptHash(script, signatures[i].ht, &s.tx, s.txidx) inner: // Find first pubkey that successfully validates signature. // we start off the search from the key that was successful @@ -1924,7 +1931,7 @@ func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error { } } success = ecdsa.Verify(pubKeys[curPk], hash, - signatures[i].R, signatures[i].S) + signatures[i].s.R, signatures[i].s.S) if success { break inner } From 76339baf6c9407b073828245e3458f4df35190ae Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Mon, 17 Mar 2014 17:43:40 +0000 Subject: [PATCH 119/174] Make removeOpcodeByData in line with bitcoind behaviour. It should remove the opcode and data is the data is contained within the data pushed, not just if it is equal to it. Found by bitcoind tx tests. --- script.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script.go b/script.go index 11f0dab3..8c918311 100644 --- a/script.go +++ b/script.go @@ -754,7 +754,7 @@ func removeOpcode(pkscript []parsedOpcode, opcode byte) []parsedOpcode { func removeOpcodeByData(pkscript []parsedOpcode, data []byte) []parsedOpcode { retScript := make([]parsedOpcode, 0, len(pkscript)) for _, pop := range pkscript { - if !bytes.Equal(pop.data, data) { + if !bytes.Contains(pop.data, data) { retScript = append(retScript, pop) } } From 1b1fef73698c5aa6ad6f184d50f12daab74eed7f Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Tue, 18 Mar 2014 17:54:29 +0000 Subject: [PATCH 120/174] Make removeOpcodeByData only search canonical pushes. Matches bitcoind behaviour. Pointed out by one of their tx_invalid tests. --- script.go | 45 +- script_test.go | 11028 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 11044 insertions(+), 29 deletions(-) diff --git a/script.go b/script.go index 8c918311..5f469685 100644 --- a/script.go +++ b/script.go @@ -325,6 +325,32 @@ func IsPushOnlyScript(script []byte) bool { return isPushOnly(pops) } +// canonicalPush returns true if the object is either not a push instruction +// or the push instruction contained wherein is matches the canonical form +// or using the smallest instruction to do the job. False otherwise. +func canonicalPush(pop parsedOpcode) bool { + opcode := pop.opcode.value + data := pop.data + dataLen := len(pop.data) + if opcode > OP_16 { + return true + } + + if opcode < OP_PUSHDATA1 && opcode > OP_0 && (dataLen == 1 && data[0] <= 16) { + return false + } + if opcode == OP_PUSHDATA1 && dataLen < OP_PUSHDATA1 { + return false + } + if opcode == OP_PUSHDATA2 && dataLen <= 0xff { + return false + } + if opcode == OP_PUSHDATA4 && dataLen <= 0xffff { + return false + } + return true +} + // HasCanonicalPushes returns whether or not the passed script only contains // canonical data pushes. A canonical data push one where the fewest number of // bytes possible to encode the size of the data being pushed is used. This @@ -337,22 +363,7 @@ func HasCanonicalPushes(script []byte) bool { } for _, pop := range pops { - opcode := pop.opcode.value - data := pop.data - dataLen := len(pop.data) - if opcode > OP_16 { - continue - } - if opcode < OP_PUSHDATA1 && opcode > OP_0 && (dataLen == 1 && data[0] <= 16) { - return false - } - if opcode == OP_PUSHDATA1 && dataLen < OP_PUSHDATA1 { - return false - } - if opcode == OP_PUSHDATA2 && dataLen <= 0xff { - return false - } - if opcode == OP_PUSHDATA4 && dataLen <= 0xffff { + if !canonicalPush(pop) { return false } } @@ -754,7 +765,7 @@ func removeOpcode(pkscript []parsedOpcode, opcode byte) []parsedOpcode { func removeOpcodeByData(pkscript []parsedOpcode, data []byte) []parsedOpcode { retScript := make([]parsedOpcode, 0, len(pkscript)) for _, pop := range pkscript { - if !bytes.Contains(pop.data, data) { + if !canonicalPush(pop) || !bytes.Contains(pop.data, data) { retScript = append(retScript, pop) } } diff --git a/script_test.go b/script_test.go index 1fb6e7a3..d32e39f2 100644 --- a/script_test.go +++ b/script_test.go @@ -1943,41 +1943,11045 @@ var removeOpcodeByDataTests = []removeOpcodeByDataTest{ after: []byte{btcscript.OP_DATA_4, 1, 2, 3, 4}, }, { - name: "simple case (pushdata1)", - before: []byte{btcscript.OP_PUSHDATA1, 4, 1, 2, 3, 4}, + // padded to keep it canonical. + name: "simple case (pushdata1)", + before: []byte{btcscript.OP_PUSHDATA1, 76, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4}, remove: []byte{1, 2, 3, 4}, after: []byte{}, }, { - name: "simple case (pushdata1 miss)", - before: []byte{btcscript.OP_PUSHDATA1, 4, 1, 2, 3, 4}, + name: "simple case (pushdata1 miss)", + before: []byte{btcscript.OP_PUSHDATA1, 76, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4}, remove: []byte{1, 2, 3, 5}, + after: []byte{btcscript.OP_PUSHDATA1, 76, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4}, + }, + { + name: "simple case (pushdata1 miss noncanonical)", + before: []byte{btcscript.OP_PUSHDATA1, 4, 1, 2, 3, 4}, + remove: []byte{1, 2, 3, 4}, after: []byte{btcscript.OP_PUSHDATA1, 4, 1, 2, 3, 4}, }, { - name: "simple case (pushdata2)", - before: []byte{btcscript.OP_PUSHDATA2, 4, 0, 1, 2, 3, 4}, + name: "simple case (pushdata2)", + before: []byte{btcscript.OP_PUSHDATA2, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4}, remove: []byte{1, 2, 3, 4}, after: []byte{}, }, { - name: "simple case (pushdata2 miss)", + name: "simple case (pushdata2 miss)", + before: []byte{btcscript.OP_PUSHDATA2, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4}, + remove: []byte{1, 2, 3, 4, 5}, + after: []byte{btcscript.OP_PUSHDATA2, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4}, + }, + { + name: "simple case (pushdata2 miss noncanonical)", before: []byte{btcscript.OP_PUSHDATA2, 4, 0, 1, 2, 3, 4}, - remove: []byte{1, 2, 3, 5}, + remove: []byte{1, 2, 3, 4}, after: []byte{btcscript.OP_PUSHDATA2, 4, 0, 1, 2, 3, 4}, }, { - name: "simple case (pushdata4)", - before: []byte{btcscript.OP_PUSHDATA4, 4, 0, 0, 0, 1, 2, 3, 4}, + // This is padded to make the push canonical. + name: "simple case (pushdata4)", + before: []byte{btcscript.OP_PUSHDATA4, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4}, remove: []byte{1, 2, 3, 4}, after: []byte{}, }, { - name: "simple case (pushdata4 miss)", + name: "simple case (pushdata4 miss noncanonical)", before: []byte{btcscript.OP_PUSHDATA4, 4, 0, 0, 0, 1, 2, 3, 4}, - remove: []byte{1, 2, 3, 4, 5}, + remove: []byte{1, 2, 3, 4}, after: []byte{btcscript.OP_PUSHDATA4, 4, 0, 0, 0, 1, 2, 3, 4}, }, + { + // This is padded to make the push canonical. + name: "simple case (pushdata4 miss)", + before: []byte{btcscript.OP_PUSHDATA4, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4}, + remove: []byte{1, 2, 3, 4, 5}, + after: []byte{btcscript.OP_PUSHDATA4, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4}, + }, { name: "invalid opcode ", before: []byte{btcscript.OP_UNKNOWN187}, From 5f6de02eb86ba6aec6d9d90883c0bbd73756c7f8 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Wed, 19 Mar 2014 00:42:39 +0000 Subject: [PATCH 121/174] use bytes.Repeat instead of my perlscript generated lists of zeros. Pointed out by davec. I'd forgotten about it. Kills just over 10k lines from the test file. --- script_test.go | 11010 +---------------------------------------------- 1 file changed, 18 insertions(+), 10992 deletions(-) diff --git a/script_test.go b/script_test.go index d32e39f2..5a65b184 100644 --- a/script_test.go +++ b/script_test.go @@ -1945,30 +1945,18 @@ var removeOpcodeByDataTests = []removeOpcodeByDataTest{ { // padded to keep it canonical. name: "simple case (pushdata1)", - before: []byte{btcscript.OP_PUSHDATA1, 76, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 3, 4}, + before: append(append([]byte{btcscript.OP_PUSHDATA1, 76,}, + bytes.Repeat([]byte{0}, 72)...), []byte{1,2,3,4}...), remove: []byte{1, 2, 3, 4}, after: []byte{}, }, { name: "simple case (pushdata1 miss)", - before: []byte{btcscript.OP_PUSHDATA1, 76, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 3, 4}, + before: append(append([]byte{btcscript.OP_PUSHDATA1, 76,}, + bytes.Repeat([]byte{0}, 72)...), []byte{1,2,3,4}...), remove: []byte{1, 2, 3, 5}, - after: []byte{btcscript.OP_PUSHDATA1, 76, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 3, 4}, + after: append(append([]byte{btcscript.OP_PUSHDATA1, 76,}, + bytes.Repeat([]byte{0}, 72)...), []byte{1,2,3,4}...), }, { name: "simple case (pushdata1 miss noncanonical)", @@ -1978,60 +1966,18 @@ var removeOpcodeByDataTests = []removeOpcodeByDataTest{ }, { name: "simple case (pushdata2)", - before: []byte{btcscript.OP_PUSHDATA2, 0, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 3, 4}, + before: append(append([]byte{btcscript.OP_PUSHDATA2, 0, 1}, + bytes.Repeat([]byte{0}, 252)...), []byte{1,2,3,4}...), remove: []byte{1, 2, 3, 4}, after: []byte{}, }, { name: "simple case (pushdata2 miss)", - before: []byte{btcscript.OP_PUSHDATA2, 0, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 3, 4}, + before: append(append([]byte{btcscript.OP_PUSHDATA2, 0, 1}, + bytes.Repeat([]byte{0}, 252)...), []byte{1,2,3,4}...), remove: []byte{1, 2, 3, 4, 5}, - after: []byte{btcscript.OP_PUSHDATA2, 0, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 3, 4}, + after: append(append([]byte{btcscript.OP_PUSHDATA2, 0, 1}, + bytes.Repeat([]byte{0}, 252)...), []byte{1,2,3,4}...), }, { name: "simple case (pushdata2 miss noncanonical)", @@ -2042,3648 +1988,8 @@ var removeOpcodeByDataTests = []removeOpcodeByDataTest{ { // This is padded to make the push canonical. name: "simple case (pushdata4)", - before: []byte{btcscript.OP_PUSHDATA4, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4}, + before: append(append([]byte{btcscript.OP_PUSHDATA4, 0, 0, 1, 0}, + bytes.Repeat([]byte{0}, 65532)...), []byte{1,2,3,4}...), remove: []byte{1, 2, 3, 4}, after: []byte{}, }, @@ -5696,7291 +2002,11 @@ var removeOpcodeByDataTests = []removeOpcodeByDataTest{ { // This is padded to make the push canonical. name: "simple case (pushdata4 miss)", - before: []byte{btcscript.OP_PUSHDATA4, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4}, + before: append(append([]byte{btcscript.OP_PUSHDATA4, 0, 0, 1, 0}, + bytes.Repeat([]byte{0}, 65532)...), []byte{1,2,3,4}...), remove: []byte{1, 2, 3, 4, 5}, - after: []byte{btcscript.OP_PUSHDATA4, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4}, + after: append(append([]byte{btcscript.OP_PUSHDATA4, 0, 0, 1, 0}, + bytes.Repeat([]byte{0}, 65532)...), []byte{1,2,3,4}...), }, { name: "invalid opcode ", From 8ec60d46784d0ff864947e8732b292a3ae510280 Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Fri, 14 Mar 2014 16:38:18 +0000 Subject: [PATCH 122/174] Quick and dirty tests harnesses using some bitcoind test data. Both the script tests (positive and negative) and tx texts (ditto) are present. Some of the tx tests in the negative section have been replaced by a comment line explaining why that test is elided, to add in diffing. The reasons were always that they test things handled by other parts of the btcd stack (normally chain). For example MAX_MONEY, number of outputs, coinbase sizes etc. Much of the inital test logic from @dajohi using hand transcribed tables for selected tests. The json parsers, script format parser and a lot of cleaning up/bugfixing from your truly. @davecgh had some input too. --- data/LICENSE | 8 + data/script_invalid.json | 329 ++++++++++++++++++++++++++++ data/script_valid.json | 415 +++++++++++++++++++++++++++++++++++ data/tx_invalid.json | 74 +++++++ data/tx_valid.json | 122 +++++++++++ internal_test.go | 458 +++++++++++++++++++++++++++++++++++++++ test_coverage.txt | 203 ++++++++--------- 7 files changed, 1508 insertions(+), 101 deletions(-) create mode 100644 data/LICENSE create mode 100644 data/script_invalid.json create mode 100644 data/script_valid.json create mode 100644 data/tx_invalid.json create mode 100644 data/tx_valid.json diff --git a/data/LICENSE b/data/LICENSE new file mode 100644 index 00000000..30d808c5 --- /dev/null +++ b/data/LICENSE @@ -0,0 +1,8 @@ +The json files in this directory come from the bitcoind project +(https://github.com/bitcoin/bitcoin) and is released under the following +license: + + Copyright (c) 2012-2014 The Bitcoin Core developers + Distributed under the MIT/X11 software license, see the accompanying + file COPYING or http://www.opensource.org/licenses/mit-license.php. + diff --git a/data/script_invalid.json b/data/script_invalid.json new file mode 100644 index 00000000..761cc4a0 --- /dev/null +++ b/data/script_invalid.json @@ -0,0 +1,329 @@ +[ +["", ""], +["", "NOP"], +["NOP", ""], +["NOP","NOP"], + +["0x4c01","0x01 NOP", "PUSHDATA1 with not enough bytes"], +["0x4d0200ff","0x01 NOP", "PUSHDATA2 with not enough bytes"], +["0x4e03000000ffff","0x01 NOP", "PUSHDATA4 with not enough bytes"], + +["1", "IF 0x50 ENDIF 1", "0x50 is reserved"], +["0x52", "0x5f ADD 0x60 EQUAL", "0x51 through 0x60 push 1 through 16 onto stack"], +["0","NOP"], +["1", "IF VER ELSE 1 ENDIF", "VER non-functional"], +["0", "IF VERIF ELSE 1 ENDIF", "VERIF illegal everywhere"], +["0", "IF ELSE 1 ELSE VERIF ENDIF", "VERIF illegal everywhere"], +["0", "IF VERNOTIF ELSE 1 ENDIF", "VERNOTIF illegal everywhere"], +["0", "IF ELSE 1 ELSE VERNOTIF ENDIF", "VERNOTIF illegal everywhere"], + +["1 IF", "1 ENDIF", "IF/ENDIF can't span scriptSig/scriptPubKey"], +["1 IF 0 ENDIF", "1 ENDIF"], +["1 ELSE 0 ENDIF", "1"], +["0 NOTIF", "123"], + +["0", "DUP IF ENDIF"], +["0", "IF 1 ENDIF"], +["0", "DUP IF ELSE ENDIF"], +["0", "IF 1 ELSE ENDIF"], +["0", "NOTIF ELSE 1 ENDIF"], + +["0 1", "IF IF 1 ELSE 0 ENDIF ENDIF"], +["0 0", "IF IF 1 ELSE 0 ENDIF ENDIF"], +["1 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], +["0 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], + +["0 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF"], +["0 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF"], +["1 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], +["0 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], + +["1", "IF RETURN ELSE ELSE 1 ENDIF", "Multiple ELSEs"], +["1", "IF 1 ELSE ELSE RETURN ENDIF"], + +["1", "ENDIF", "Malformed IF/ELSE/ENDIF sequence"], +["1", "ELSE ENDIF"], +["1", "ENDIF ELSE"], +["1", "ENDIF ELSE IF"], +["1", "IF ELSE ENDIF ELSE"], +["1", "IF ELSE ENDIF ELSE ENDIF"], +["1", "IF ENDIF ENDIF"], +["1", "IF ELSE ELSE ENDIF ENDIF"], + +["1", "RETURN"], +["1", "DUP IF RETURN ENDIF"], + +["1", "RETURN 'data'", "canonical prunable txout format"], +["0 IF", "RETURN ENDIF 1", "still prunable because IF/ENDIF can't span scriptSig/scriptPubKey"], + +["0", "VERIFY 1"], +["1", "VERIFY"], +["1", "VERIFY 0"], + +["1 TOALTSTACK", "FROMALTSTACK 1", "alt stack not shared between sig/pubkey"], + +["IFDUP", "DEPTH 0 EQUAL"], +["DROP", "DEPTH 0 EQUAL"], +["DUP", "DEPTH 0 EQUAL"], +["1", "DUP 1 ADD 2 EQUALVERIFY 0 EQUAL"], +["NOP", "NIP"], +["NOP", "1 NIP"], +["NOP", "1 0 NIP"], +["NOP", "OVER 1"], +["1", "OVER"], +["0 1", "OVER DEPTH 3 EQUALVERIFY"], +["19 20 21", "PICK 19 EQUALVERIFY DEPTH 2 EQUAL"], +["NOP", "0 PICK"], +["1", "-1 PICK"], +["19 20 21", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL"], +["19 20 21", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL"], +["19 20 21", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL"], +["NOP", "0 ROLL"], +["1", "-1 ROLL"], +["19 20 21", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL"], +["19 20 21", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL"], +["19 20 21", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL"], +["NOP", "ROT 1"], +["NOP", "1 ROT 1"], +["NOP", "1 2 ROT 1"], +["NOP", "0 1 2 ROT"], +["NOP", "SWAP 1"], +["1", "SWAP 1"], +["0 1", "SWAP 1 EQUALVERIFY"], +["NOP", "TUCK 1"], +["1", "TUCK 1"], +["1 0", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP"], +["NOP", "2DUP 1"], +["1", "2DUP 1"], +["NOP", "3DUP 1"], +["1", "3DUP 1"], +["1 2", "3DUP 1"], +["NOP", "2OVER 1"], +["1", "2 3 2OVER 1"], +["NOP", "2SWAP 1"], +["1", "2 3 2SWAP 1"], + +["'a' 'b'", "CAT", "CAT disabled"], +["'a' 'b' 0", "IF CAT ELSE 1 ENDIF", "CAT disabled"], +["'abc' 1 1", "SUBSTR", "SUBSTR disabled"], +["'abc' 1 1 0", "IF SUBSTR ELSE 1 ENDIF", "SUBSTR disabled"], +["'abc' 2 0", "IF LEFT ELSE 1 ENDIF", "LEFT disabled"], +["'abc' 2 0", "IF RIGHT ELSE 1 ENDIF", "RIGHT disabled"], + +["NOP", "SIZE 1"], + +["'abc'", "IF INVERT ELSE 1 ENDIF", "INVERT disabled"], +["1 2 0 IF AND ELSE 1 ENDIF", "NOP", "AND disabled"], +["1 2 0 IF OR ELSE 1 ENDIF", "NOP", "OR disabled"], +["1 2 0 IF XOR ELSE 1 ENDIF", "NOP", "XOR disabled"], +["2 0 IF 2MUL ELSE 1 ENDIF", "NOP", "2MUL disabled"], +["2 0 IF 2DIV ELSE 1 ENDIF", "NOP", "2DIV disabled"], +["2 2 0 IF MUL ELSE 1 ENDIF", "NOP", "MUL disabled"], +["2 2 0 IF DIV ELSE 1 ENDIF", "NOP", "DIV disabled"], +["2 2 0 IF MOD ELSE 1 ENDIF", "NOP", "MOD disabled"], +["2 2 0 IF LSHIFT ELSE 1 ENDIF", "NOP", "LSHIFT disabled"], +["2 2 0 IF RSHIFT ELSE 1 ENDIF", "NOP", "RSHIFT disabled"], + +["0 1","EQUAL"], +["1 1 ADD", "0 EQUAL"], +["11 1 ADD 12 SUB", "11 EQUAL"], + +["2147483648 0 ADD", "NOP", "arithmetic operands must be in range [-2^31...2^31] "], +["-2147483648 0 ADD", "NOP", "arithmetic operands must be in range [-2^31...2^31] "], +["2147483647 DUP ADD", "4294967294 NUMEQUAL", "NUMEQUAL must be in numeric range"], +["'abcdef' NOT", "0 EQUAL", "NOT is an arithmetic operand"], + +["2 DUP MUL", "4 EQUAL", "disabled"], +["2 DUP DIV", "1 EQUAL", "disabled"], +["2 2MUL", "4 EQUAL", "disabled"], +["2 2DIV", "1 EQUAL", "disabled"], +["7 3 MOD", "1 EQUAL", "disabled"], +["2 2 LSHIFT", "8 EQUAL", "disabled"], +["2 1 RSHIFT", "1 EQUAL", "disabled"], + +["1","NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL"], +["'NOP_1_to_10' NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL"], + +["0x50","1", "opcode 0x50 is reserved"], +["1", "IF 0xba ELSE 1 ENDIF", "opcodes above NOP10 invalid if executed"], +["1", "IF 0xbb ELSE 1 ENDIF"], +["1", "IF 0xbc ELSE 1 ENDIF"], +["1", "IF 0xbd ELSE 1 ENDIF"], +["1", "IF 0xbe ELSE 1 ENDIF"], +["1", "IF 0xbf ELSE 1 ENDIF"], +["1", "IF 0xc0 ELSE 1 ENDIF"], +["1", "IF 0xc1 ELSE 1 ENDIF"], +["1", "IF 0xc2 ELSE 1 ENDIF"], +["1", "IF 0xc3 ELSE 1 ENDIF"], +["1", "IF 0xc4 ELSE 1 ENDIF"], +["1", "IF 0xc5 ELSE 1 ENDIF"], +["1", "IF 0xc6 ELSE 1 ENDIF"], +["1", "IF 0xc7 ELSE 1 ENDIF"], +["1", "IF 0xc8 ELSE 1 ENDIF"], +["1", "IF 0xc9 ELSE 1 ENDIF"], +["1", "IF 0xca ELSE 1 ENDIF"], +["1", "IF 0xcb ELSE 1 ENDIF"], +["1", "IF 0xcc ELSE 1 ENDIF"], +["1", "IF 0xcd ELSE 1 ENDIF"], +["1", "IF 0xce ELSE 1 ENDIF"], +["1", "IF 0xcf ELSE 1 ENDIF"], +["1", "IF 0xd0 ELSE 1 ENDIF"], +["1", "IF 0xd1 ELSE 1 ENDIF"], +["1", "IF 0xd2 ELSE 1 ENDIF"], +["1", "IF 0xd3 ELSE 1 ENDIF"], +["1", "IF 0xd4 ELSE 1 ENDIF"], +["1", "IF 0xd5 ELSE 1 ENDIF"], +["1", "IF 0xd6 ELSE 1 ENDIF"], +["1", "IF 0xd7 ELSE 1 ENDIF"], +["1", "IF 0xd8 ELSE 1 ENDIF"], +["1", "IF 0xd9 ELSE 1 ENDIF"], +["1", "IF 0xda ELSE 1 ENDIF"], +["1", "IF 0xdb ELSE 1 ENDIF"], +["1", "IF 0xdc ELSE 1 ENDIF"], +["1", "IF 0xdd ELSE 1 ENDIF"], +["1", "IF 0xde ELSE 1 ENDIF"], +["1", "IF 0xdf ELSE 1 ENDIF"], +["1", "IF 0xe0 ELSE 1 ENDIF"], +["1", "IF 0xe1 ELSE 1 ENDIF"], +["1", "IF 0xe2 ELSE 1 ENDIF"], +["1", "IF 0xe3 ELSE 1 ENDIF"], +["1", "IF 0xe4 ELSE 1 ENDIF"], +["1", "IF 0xe5 ELSE 1 ENDIF"], +["1", "IF 0xe6 ELSE 1 ENDIF"], +["1", "IF 0xe7 ELSE 1 ENDIF"], +["1", "IF 0xe8 ELSE 1 ENDIF"], +["1", "IF 0xe9 ELSE 1 ENDIF"], +["1", "IF 0xea ELSE 1 ENDIF"], +["1", "IF 0xeb ELSE 1 ENDIF"], +["1", "IF 0xec ELSE 1 ENDIF"], +["1", "IF 0xed ELSE 1 ENDIF"], +["1", "IF 0xee ELSE 1 ENDIF"], +["1", "IF 0xef ELSE 1 ENDIF"], +["1", "IF 0xf0 ELSE 1 ENDIF"], +["1", "IF 0xf1 ELSE 1 ENDIF"], +["1", "IF 0xf2 ELSE 1 ENDIF"], +["1", "IF 0xf3 ELSE 1 ENDIF"], +["1", "IF 0xf4 ELSE 1 ENDIF"], +["1", "IF 0xf5 ELSE 1 ENDIF"], +["1", "IF 0xf6 ELSE 1 ENDIF"], +["1", "IF 0xf7 ELSE 1 ENDIF"], +["1", "IF 0xf8 ELSE 1 ENDIF"], +["1", "IF 0xf9 ELSE 1 ENDIF"], +["1", "IF 0xfa ELSE 1 ENDIF"], +["1", "IF 0xfb ELSE 1 ENDIF"], +["1", "IF 0xfc ELSE 1 ENDIF"], +["1", "IF 0xfd ELSE 1 ENDIF"], +["1", "IF 0xfe ELSE 1 ENDIF"], +["1", "IF 0xff ELSE 1 ENDIF"], + +["1 IF 1 ELSE", "0xff ENDIF", "invalid because scriptSig and scriptPubKey are processed separately"], + +["NOP", "RIPEMD160"], +["NOP", "SHA1"], +["NOP", "SHA256"], +["NOP", "HASH160"], +["NOP", "HASH256"], + +["NOP", +"'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'", +">520 byte push"], +["0", +"IF 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' ENDIF 1", +">520 byte push in non-executed IF branch"], +["1", +"0x61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", +">201 opcodes executed. 0x61 is NOP"], +["0", +"IF 0x6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161 ENDIF 1", +">201 opcodes including non-executed IF branch. 0x61 is NOP"], +["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"1 2 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +">1,000 stack size (0x6f is 3DUP)"], +["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"1 TOALTSTACK 2 TOALTSTACK 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +">1,000 stack+altstack size"], +["NOP", +"0 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f 2DUP 0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", +"10,001-byte scriptPubKey"], + +["NOP1","NOP10"], + +["1","VER", "OP_VER is reserved"], +["1","VERIF", "OP_VERIF is reserved"], +["1","VERNOTIF", "OP_VERNOTIF is reserved"], +["1","RESERVED", "OP_RESERVED is reserved"], +["1","RESERVED1", "OP_RESERVED1 is reserved"], +["1","RESERVED2", "OP_RESERVED2 is reserved"], +["1","0xba", "0xba == OP_NOP10 + 1"], + +["2147483648", "1ADD 1", "We cannot do math on 5-byte integers"], +["-2147483648", "1ADD 1", "Because we use a sign bit, -2147483648 is also 5 bytes"], + +["1", "1 ENDIF", "ENDIF without IF"], +["1", "IF 1", "IF without ENDIF"], +["1 IF 1", "ENDIF", "IFs don't carry over"], + +["NOP", "IF 1 ENDIF", "The following tests check the if(stack.size() < N) tests in each opcode"], +["NOP", "NOTIF 1 ENDIF", "They are here to catch copy-and-paste errors"], +["NOP", "VERIFY 1", "Most of them are duplicated elsewhere,"], + +["NOP", "TOALTSTACK 1", "but, hey, more is always better, right?"], +["1", "FROMALTSTACK"], +["1", "2DROP 1"], +["1", "2DUP"], +["1 1", "3DUP"], +["1 1 1", "2OVER"], +["1 1 1 1 1", "2ROT"], +["1 1 1", "2SWAP"], +["NOP", "IFDUP 1"], +["NOP", "DROP 1"], +["NOP", "DUP 1"], +["1", "NIP"], +["1", "OVER"], +["1 1 1 3", "PICK"], +["0", "PICK 1"], +["1 1 1 3", "ROLL"], +["0", "ROLL 1"], +["1 1", "ROT"], +["1", "SWAP"], +["1", "TUCK"], + +["NOP", "SIZE 1"], + +["1", "EQUAL 1"], +["1", "EQUALVERIFY 1"], + +["NOP", "1ADD 1"], +["NOP", "1SUB 1"], +["NOP", "NEGATE 1"], +["NOP", "ABS 1"], +["NOP", "NOT 1"], +["NOP", "0NOTEQUAL 1"], + +["1", "ADD"], +["1", "SUB"], +["1", "BOOLAND"], +["1", "BOOLOR"], +["1", "NUMEQUAL"], +["1", "NUMEQUALVERIFY 1"], +["1", "NUMNOTEQUAL"], +["1", "LESSTHAN"], +["1", "GREATERTHAN"], +["1", "LESSTHANOREQUAL"], +["1", "GREATERTHANOREQUAL"], +["1", "MIN"], +["1", "MAX"], +["1 1", "WITHIN"], + +["NOP", "RIPEMD160 1"], +["NOP", "SHA1 1"], +["NOP", "SHA256 1"], +["NOP", "HASH160 1"], +["NOP", "HASH256 1"], + +["NOP 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "Tests for Script.IsPushOnly()"], +["NOP1 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL"], + +["0 0x01 0x50", "HASH160 0x14 0xece424a6bb6ddf4db592c0faed60685047a361b1 EQUAL", "OP_RESERVED in P2SH should fail"], +["0 0x01 VER", "HASH160 0x14 0x0f4d7845db968f2a81b530b6f3c1d6246d4c7e01 EQUAL", "OP_VER in P2SH should fail"] +] diff --git a/data/script_valid.json b/data/script_valid.json new file mode 100644 index 00000000..e4c181ca --- /dev/null +++ b/data/script_valid.json @@ -0,0 +1,415 @@ +[ +["0x01 0x0b", "11 EQUAL", "push 1 byte"], +["0x02 0x417a", "'Az' EQUAL"], +["0x4b 0x417a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a", + "'Azzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' EQUAL", "push 75 bytes"], + +["0x4c 0x01 0x07","7 EQUAL", "0x4c is OP_PUSHDATA1"], +["0x4d 0x0100 0x08","8 EQUAL", "0x4d is OP_PUSHDATA2"], +["0x4e 0x01000000 0x09","9 EQUAL", "0x4e is OP_PUSHDATA4"], + +["0x4c 0x00","0 EQUAL"], +["0x4d 0x0000","0 EQUAL"], +["0x4e 0x00000000","0 EQUAL"], +["0x4f 1000 ADD","999 EQUAL"], +["0", "IF 0x50 ENDIF 1", "0x50 is reserved (ok if not executed)"], +["0x51", "0x5f ADD 0x60 EQUAL", "0x51 through 0x60 push 1 through 16 onto stack"], +["1","NOP"], +["0", "IF VER ELSE 1 ENDIF", "VER non-functional (ok if not executed)"], +["0", "IF RESERVED RESERVED1 RESERVED2 ELSE 1 ENDIF", "RESERVED ok in un-executed IF"], + +["1", "DUP IF ENDIF"], +["1", "IF 1 ENDIF"], +["1", "DUP IF ELSE ENDIF"], +["1", "IF 1 ELSE ENDIF"], +["0", "IF ELSE 1 ENDIF"], + +["1 1", "IF IF 1 ELSE 0 ENDIF ENDIF"], +["1 0", "IF IF 1 ELSE 0 ENDIF ENDIF"], +["1 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], +["0 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], + +["1 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF"], +["1 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF"], +["1 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], +["0 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], + +["0", "IF 0 ELSE 1 ELSE 0 ENDIF", "Multiple ELSE's are valid and executed inverts on each ELSE encountered"], +["1", "IF 1 ELSE 0 ELSE ENDIF"], +["1", "IF ELSE 0 ELSE 1 ENDIF"], +["1", "IF 1 ELSE 0 ELSE 1 ENDIF ADD 2 EQUAL"], +["'' 1", "IF SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ENDIF 0x14 0x68ca4fec736264c13b859bac43d5173df6871682 EQUAL"], + +["1", "NOTIF 0 ELSE 1 ELSE 0 ENDIF", "Multiple ELSE's are valid and execution inverts on each ELSE encountered"], +["0", "NOTIF 1 ELSE 0 ELSE ENDIF"], +["0", "NOTIF ELSE 0 ELSE 1 ENDIF"], +["0", "NOTIF 1 ELSE 0 ELSE 1 ENDIF ADD 2 EQUAL"], +["'' 0", "NOTIF SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ENDIF 0x14 0x68ca4fec736264c13b859bac43d5173df6871682 EQUAL"], + +["0", "IF 1 IF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 1 IF 1 ELSE RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL", "Nested ELSE ELSE"], +["1", "NOTIF 0 NOTIF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 0 NOTIF 1 ELSE RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL"], + +["0", "IF RETURN ENDIF 1", "RETURN only works if executed"], + +["1 1", "VERIFY"], + +["10 0 11 TOALTSTACK DROP FROMALTSTACK", "ADD 21 EQUAL"], +["'gavin_was_here' TOALTSTACK 11 FROMALTSTACK", "'gavin_was_here' EQUALVERIFY 11 EQUAL"], + +["0 IFDUP", "DEPTH 1 EQUALVERIFY 0 EQUAL"], +["1 IFDUP", "DEPTH 2 EQUALVERIFY 1 EQUALVERIFY 1 EQUAL"], +["0 DROP", "DEPTH 0 EQUAL"], +["0", "DUP 1 ADD 1 EQUALVERIFY 0 EQUAL"], +["0 1", "NIP"], +["1 0", "OVER DEPTH 3 EQUALVERIFY"], +["22 21 20", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL"], +["22 21 20", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL"], +["22 21 20", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL"], +["22 21 20", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL"], +["22 21 20", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL"], +["22 21 20", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL"], +["22 21 20", "ROT 22 EQUAL"], +["22 21 20", "ROT DROP 20 EQUAL"], +["22 21 20", "ROT DROP DROP 21 EQUAL"], +["22 21 20", "ROT ROT 21 EQUAL"], +["22 21 20", "ROT ROT ROT 20 EQUAL"], +["25 24 23 22 21 20", "2ROT 24 EQUAL"], +["25 24 23 22 21 20", "2ROT DROP 25 EQUAL"], +["25 24 23 22 21 20", "2ROT 2DROP 20 EQUAL"], +["25 24 23 22 21 20", "2ROT 2DROP DROP 21 EQUAL"], +["25 24 23 22 21 20", "2ROT 2DROP 2DROP 22 EQUAL"], +["25 24 23 22 21 20", "2ROT 2DROP 2DROP DROP 23 EQUAL"], +["25 24 23 22 21 20", "2ROT 2ROT 22 EQUAL"], +["25 24 23 22 21 20", "2ROT 2ROT 2ROT 20 EQUAL"], +["1 0", "SWAP 1 EQUALVERIFY 0 EQUAL"], +["0 1", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP"], +["13 14", "2DUP ROT EQUALVERIFY EQUAL"], +["-1 0 1 2", "3DUP DEPTH 7 EQUALVERIFY ADD ADD 3 EQUALVERIFY 2DROP 0 EQUALVERIFY"], +["1 2 3 5", "2OVER ADD ADD 8 EQUALVERIFY ADD ADD 6 EQUAL"], +["1 3 5 7", "2SWAP ADD 4 EQUALVERIFY ADD 12 EQUAL"], +["0", "SIZE 0 EQUAL"], +["1", "SIZE 1 EQUAL"], +["127", "SIZE 1 EQUAL"], +["128", "SIZE 2 EQUAL"], +["32767", "SIZE 2 EQUAL"], +["32768", "SIZE 3 EQUAL"], +["8388607", "SIZE 3 EQUAL"], +["8388608", "SIZE 4 EQUAL"], +["2147483647", "SIZE 4 EQUAL"], +["2147483648", "SIZE 5 EQUAL"], +["-1", "SIZE 1 EQUAL"], +["-127", "SIZE 1 EQUAL"], +["-128", "SIZE 2 EQUAL"], +["-32767", "SIZE 2 EQUAL"], +["-32768", "SIZE 3 EQUAL"], +["-8388607", "SIZE 3 EQUAL"], +["-8388608", "SIZE 4 EQUAL"], +["-2147483647", "SIZE 4 EQUAL"], +["-2147483648", "SIZE 5 EQUAL"], +["'abcdefghijklmnopqrstuvwxyz'", "SIZE 26 EQUAL"], + + +["2 -2 ADD", "0 EQUAL"], +["2147483647 -2147483647 ADD", "0 EQUAL"], +["-1 -1 ADD", "-2 EQUAL"], + +["0 0","EQUAL"], +["1 1 ADD", "2 EQUAL"], +["1 1ADD", "2 EQUAL"], +["111 1SUB", "110 EQUAL"], +["111 1 ADD 12 SUB", "100 EQUAL"], +["0 ABS", "0 EQUAL"], +["16 ABS", "16 EQUAL"], +["-16 ABS", "-16 NEGATE EQUAL"], +["0 NOT", "NOP"], +["1 NOT", "0 EQUAL"], +["11 NOT", "0 EQUAL"], +["0 0NOTEQUAL", "0 EQUAL"], +["1 0NOTEQUAL", "1 EQUAL"], +["111 0NOTEQUAL", "1 EQUAL"], +["-111 0NOTEQUAL", "1 EQUAL"], +["1 1 BOOLAND", "NOP"], +["1 0 BOOLAND", "NOT"], +["0 1 BOOLAND", "NOT"], +["0 0 BOOLAND", "NOT"], +["16 17 BOOLAND", "NOP"], +["1 1 BOOLOR", "NOP"], +["1 0 BOOLOR", "NOP"], +["0 1 BOOLOR", "NOP"], +["0 0 BOOLOR", "NOT"], +["16 17 BOOLOR", "NOP"], +["11 10 1 ADD", "NUMEQUAL"], +["11 10 1 ADD", "NUMEQUALVERIFY 1"], +["11 10 1 ADD", "NUMNOTEQUAL NOT"], +["111 10 1 ADD", "NUMNOTEQUAL"], +["11 10", "LESSTHAN NOT"], +["4 4", "LESSTHAN NOT"], +["10 11", "LESSTHAN"], +["-11 11", "LESSTHAN"], +["-11 -10", "LESSTHAN"], +["11 10", "GREATERTHAN"], +["4 4", "GREATERTHAN NOT"], +["10 11", "GREATERTHAN NOT"], +["-11 11", "GREATERTHAN NOT"], +["-11 -10", "GREATERTHAN NOT"], +["11 10", "LESSTHANOREQUAL NOT"], +["4 4", "LESSTHANOREQUAL"], +["10 11", "LESSTHANOREQUAL"], +["-11 11", "LESSTHANOREQUAL"], +["-11 -10", "LESSTHANOREQUAL"], +["11 10", "GREATERTHANOREQUAL"], +["4 4", "GREATERTHANOREQUAL"], +["10 11", "GREATERTHANOREQUAL NOT"], +["-11 11", "GREATERTHANOREQUAL NOT"], +["-11 -10", "GREATERTHANOREQUAL NOT"], +["1 0 MIN", "0 NUMEQUAL"], +["0 1 MIN", "0 NUMEQUAL"], +["-1 0 MIN", "-1 NUMEQUAL"], +["0 -2147483647 MIN", "-2147483647 NUMEQUAL"], +["2147483647 0 MAX", "2147483647 NUMEQUAL"], +["0 100 MAX", "100 NUMEQUAL"], +["-100 0 MAX", "0 NUMEQUAL"], +["0 -2147483647 MAX", "0 NUMEQUAL"], +["0 0 1", "WITHIN"], +["1 0 1", "WITHIN NOT"], +["0 -2147483647 2147483647", "WITHIN"], +["-1 -100 100", "WITHIN"], +["11 -100 100", "WITHIN"], +["-2147483647 -100 100", "WITHIN NOT"], +["2147483647 -100 100", "WITHIN NOT"], + +["2147483647 2147483647 SUB", "0 EQUAL"], +["2147483647 DUP ADD", "4294967294 EQUAL", ">32 bit EQUAL is valid"], +["2147483647 NEGATE DUP ADD", "-4294967294 EQUAL"], + +["''", "RIPEMD160 0x14 0x9c1185a5c5e9fc54612808977ee8f548b2258d31 EQUAL"], +["'a'", "RIPEMD160 0x14 0x0bdc9d2d256b3ee9daae347be6f4dc835a467ffe EQUAL"], +["'abcdefghijklmnopqrstuvwxyz'", "RIPEMD160 0x14 0xf71c27109c692c1b56bbdceb5b9d2865b3708dbc EQUAL"], +["''", "SHA1 0x14 0xda39a3ee5e6b4b0d3255bfef95601890afd80709 EQUAL"], +["'a'", "SHA1 0x14 0x86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 EQUAL"], +["'abcdefghijklmnopqrstuvwxyz'", "SHA1 0x14 0x32d10c7b8cf96570ca04ce37f2a19d84240d3a89 EQUAL"], +["''", "SHA256 0x20 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 EQUAL"], +["'a'", "SHA256 0x20 0xca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb EQUAL"], +["'abcdefghijklmnopqrstuvwxyz'", "SHA256 0x20 0x71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73 EQUAL"], +["''", "DUP HASH160 SWAP SHA256 RIPEMD160 EQUAL"], +["''", "DUP HASH256 SWAP SHA256 SHA256 EQUAL"], +["''", "NOP HASH160 0x14 0xb472a266d0bd89c13706a4132ccfb16f7c3b9fcb EQUAL"], +["'a'", "HASH160 NOP 0x14 0x994355199e516ff76c4fa4aab39337b9d84cf12b EQUAL"], +["'abcdefghijklmnopqrstuvwxyz'", "HASH160 0x4c 0x14 0xc286a1af0947f58d1ad787385b1c2c4a976f9e71 EQUAL"], +["''", "HASH256 0x20 0x5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456 EQUAL"], +["'a'", "HASH256 0x20 0xbf5d3affb73efd2ec6c36ad3112dd933efed63c4e1cbffcfa88e2759c144f2d8 EQUAL"], +["'abcdefghijklmnopqrstuvwxyz'", "HASH256 0x4c 0x20 0xca139bc10c2f660da42666f72e89a225936fc60f193c161124a672050c434671 EQUAL"], + + +["1","NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 1 EQUAL"], +["'NOP_1_to_10' NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' EQUAL"], + +["0", "IF 0xba ELSE 1 ENDIF", "opcodes above NOP10 invalid if executed"], +["0", "IF 0xbb ELSE 1 ENDIF"], +["0", "IF 0xbc ELSE 1 ENDIF"], +["0", "IF 0xbd ELSE 1 ENDIF"], +["0", "IF 0xbe ELSE 1 ENDIF"], +["0", "IF 0xbf ELSE 1 ENDIF"], +["0", "IF 0xc0 ELSE 1 ENDIF"], +["0", "IF 0xc1 ELSE 1 ENDIF"], +["0", "IF 0xc2 ELSE 1 ENDIF"], +["0", "IF 0xc3 ELSE 1 ENDIF"], +["0", "IF 0xc4 ELSE 1 ENDIF"], +["0", "IF 0xc5 ELSE 1 ENDIF"], +["0", "IF 0xc6 ELSE 1 ENDIF"], +["0", "IF 0xc7 ELSE 1 ENDIF"], +["0", "IF 0xc8 ELSE 1 ENDIF"], +["0", "IF 0xc9 ELSE 1 ENDIF"], +["0", "IF 0xca ELSE 1 ENDIF"], +["0", "IF 0xcb ELSE 1 ENDIF"], +["0", "IF 0xcc ELSE 1 ENDIF"], +["0", "IF 0xcd ELSE 1 ENDIF"], +["0", "IF 0xce ELSE 1 ENDIF"], +["0", "IF 0xcf ELSE 1 ENDIF"], +["0", "IF 0xd0 ELSE 1 ENDIF"], +["0", "IF 0xd1 ELSE 1 ENDIF"], +["0", "IF 0xd2 ELSE 1 ENDIF"], +["0", "IF 0xd3 ELSE 1 ENDIF"], +["0", "IF 0xd4 ELSE 1 ENDIF"], +["0", "IF 0xd5 ELSE 1 ENDIF"], +["0", "IF 0xd6 ELSE 1 ENDIF"], +["0", "IF 0xd7 ELSE 1 ENDIF"], +["0", "IF 0xd8 ELSE 1 ENDIF"], +["0", "IF 0xd9 ELSE 1 ENDIF"], +["0", "IF 0xda ELSE 1 ENDIF"], +["0", "IF 0xdb ELSE 1 ENDIF"], +["0", "IF 0xdc ELSE 1 ENDIF"], +["0", "IF 0xdd ELSE 1 ENDIF"], +["0", "IF 0xde ELSE 1 ENDIF"], +["0", "IF 0xdf ELSE 1 ENDIF"], +["0", "IF 0xe0 ELSE 1 ENDIF"], +["0", "IF 0xe1 ELSE 1 ENDIF"], +["0", "IF 0xe2 ELSE 1 ENDIF"], +["0", "IF 0xe3 ELSE 1 ENDIF"], +["0", "IF 0xe4 ELSE 1 ENDIF"], +["0", "IF 0xe5 ELSE 1 ENDIF"], +["0", "IF 0xe6 ELSE 1 ENDIF"], +["0", "IF 0xe7 ELSE 1 ENDIF"], +["0", "IF 0xe8 ELSE 1 ENDIF"], +["0", "IF 0xe9 ELSE 1 ENDIF"], +["0", "IF 0xea ELSE 1 ENDIF"], +["0", "IF 0xeb ELSE 1 ENDIF"], +["0", "IF 0xec ELSE 1 ENDIF"], +["0", "IF 0xed ELSE 1 ENDIF"], +["0", "IF 0xee ELSE 1 ENDIF"], +["0", "IF 0xef ELSE 1 ENDIF"], +["0", "IF 0xf0 ELSE 1 ENDIF"], +["0", "IF 0xf1 ELSE 1 ENDIF"], +["0", "IF 0xf2 ELSE 1 ENDIF"], +["0", "IF 0xf3 ELSE 1 ENDIF"], +["0", "IF 0xf4 ELSE 1 ENDIF"], +["0", "IF 0xf5 ELSE 1 ENDIF"], +["0", "IF 0xf6 ELSE 1 ENDIF"], +["0", "IF 0xf7 ELSE 1 ENDIF"], +["0", "IF 0xf8 ELSE 1 ENDIF"], +["0", "IF 0xf9 ELSE 1 ENDIF"], +["0", "IF 0xfa ELSE 1 ENDIF"], +["0", "IF 0xfb ELSE 1 ENDIF"], +["0", "IF 0xfc ELSE 1 ENDIF"], +["0", "IF 0xfd ELSE 1 ENDIF"], +["0", "IF 0xfe ELSE 1 ENDIF"], +["0", "IF 0xff ELSE 1 ENDIF"], + +["NOP", +"'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'", +"520 byte push"], +["1", +"0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", +"201 opcodes executed. 0x61 is NOP"], +["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"1,000 stack size (0x6f is 3DUP)"], +["1 TOALTSTACK 2 TOALTSTACK 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"1 2 3 4 5 6 7 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"1,000 stack size (altstack cleared between scriptSig/scriptPubKey)"], +["'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f 2DUP 0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", +"Max-size (10,000-byte), max-push(520 bytes), max-opcodes(201), max stack size(1,000 items). 0x6f is 3DUP, 0x61 is NOP"], + +["0", +"IF 0x5050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050 ENDIF 1", +">201 opcodes, but RESERVED (0x50) doesn't count towards opcode limit."], + +["NOP","1"], + +["1", "0x01 0x01 EQUAL", "The following is useful for checking implementations of BN_bn2mpi"], +["127", "0x01 0x7F EQUAL"], +["128", "0x02 0x8000 EQUAL", "Leave room for the sign bit"], +["32767", "0x02 0xFF7F EQUAL"], +["32768", "0x03 0x008000 EQUAL"], +["8388607", "0x03 0xFFFF7F EQUAL"], +["8388608", "0x04 0x00008000 EQUAL"], +["2147483647", "0x04 0xFFFFFF7F EQUAL"], +["2147483648", "0x05 0x0000008000 EQUAL"], +["-1", "0x01 0x81 EQUAL", "Numbers are little-endian with the MSB being a sign bit"], +["-127", "0x01 0xFF EQUAL"], +["-128", "0x02 0x8080 EQUAL"], +["-32767", "0x02 0xFFFF EQUAL"], +["-32768", "0x03 0x008080 EQUAL"], +["-8388607", "0x03 0xFFFFFF EQUAL"], +["-8388608", "0x04 0x00008080 EQUAL"], +["-2147483647", "0x04 0xFFFFFFFF EQUAL"], +["-2147483648", "0x05 0x0000008080 EQUAL"], + +["2147483647", "1ADD 2147483648 EQUAL", "We can do math on 4-byte integers, and compare 5-byte ones"], +["2147483647", "1ADD 1"], +["-2147483647", "1ADD 1"], + +["1", "0x02 0x0100 EQUAL NOT", "Not the same byte array..."], +["1", "0x02 0x0100 NUMEQUAL", "... but they are numerically equal"], +["11", "0x4c 0x03 0x0b0000 NUMEQUAL"], +["0", "0x01 0x80 EQUAL NOT"], +["0", "0x01 0x80 NUMEQUAL", "Zero numerically equals negative zero"], +["0", "0x02 0x0080 NUMEQUAL"], +["0x03 0x000080", "0x04 0x00000080 NUMEQUAL"], +["0x03 0x100080", "0x04 0x10000080 NUMEQUAL"], +["0x03 0x100000", "0x04 0x10000000 NUMEQUAL"], + +["NOP", "NOP 1", "The following tests check the if(stack.size() < N) tests in each opcode"], +["1", "IF 1 ENDIF", "They are here to catch copy-and-paste errors"], +["0", "NOTIF 1 ENDIF", "Most of them are duplicated elsewhere,"], +["1", "VERIFY 1", "but, hey, more is always better, right?"], + +["0", "TOALTSTACK 1"], +["1", "TOALTSTACK FROMALTSTACK"], +["0 0", "2DROP 1"], +["0 1", "2DUP"], +["0 0 1", "3DUP"], +["0 1 0 0", "2OVER"], +["0 1 0 0 0 0", "2ROT"], +["0 1 0 0", "2SWAP"], +["1", "IFDUP"], +["NOP", "DEPTH 1"], +["0", "DROP 1"], +["1", "DUP"], +["0 1", "NIP"], +["1 0", "OVER"], +["1 0 0 0 3", "PICK"], +["1 0", "PICK"], +["1 0 0 0 3", "ROLL"], +["1 0", "ROLL"], +["1 0 0", "ROT"], +["1 0", "SWAP"], +["0 1", "TUCK"], + +["1", "SIZE"], + +["0 0", "EQUAL"], +["0 0", "EQUALVERIFY 1"], + +["0", "1ADD"], +["2", "1SUB"], +["-1", "NEGATE"], +["-1", "ABS"], +["0", "NOT"], +["-1", "0NOTEQUAL"], + +["1 0", "ADD"], +["1 0", "SUB"], +["-1 -1", "BOOLAND"], +["-1 0", "BOOLOR"], +["0 0", "NUMEQUAL"], +["0 0", "NUMEQUALVERIFY 1"], +["-1 0", "NUMNOTEQUAL"], +["-1 0", "LESSTHAN"], +["1 0", "GREATERTHAN"], +["0 0", "LESSTHANOREQUAL"], +["0 0", "GREATERTHANOREQUAL"], +["-1 0", "MIN"], +["1 0", "MAX"], +["-1 -1 0", "WITHIN"], + +["0", "RIPEMD160"], +["0", "SHA1"], +["0", "SHA256"], +["0", "HASH160"], +["0", "HASH256"], +["NOP", "CODESEPARATOR 1"], + +["NOP", "NOP1 1"], +["NOP", "NOP2 1"], +["NOP", "NOP3 1"], +["NOP", "NOP4 1"], +["NOP", "NOP5 1"], +["NOP", "NOP6 1"], +["NOP", "NOP7 1"], +["NOP", "NOP8 1"], +["NOP", "NOP9 1"], +["NOP", "NOP10 1"], + +["0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "Very basic P2SH"], +["0x4c 0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL"], + +["0x40 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242", +"0x4d 0x4000 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 EQUAL", +"Basic PUSH signedness check"], + +["0x4c 0x40 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242", +"0x4d 0x4000 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 EQUAL", +"Basic PUSHDATA1 signedness check"] +] diff --git a/data/tx_invalid.json b/data/tx_invalid.json new file mode 100644 index 00000000..3d490a6e --- /dev/null +++ b/data/tx_invalid.json @@ -0,0 +1,74 @@ +[ +["The following are deserialized transactions which are invalid."], +["They are in the form"], +["[[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], +["serializedTransaction, enforceP2SH]"], +["Objects that are only a single string (like this one) are ignored"], + +["0e1b5688cf179cd9f7cbda1fac0090f6e684bbf8cd946660120197c3f3681809 but with extra junk appended to the end of the scriptPubKey"], +[[["6ca7ec7b1847f6bdbd737176050e6a08d66ccd55bb94ad24f4018024107a5827", 0, "0x41 0x043b640e983c9690a14c039a2037ecc3467b27a0dcd58f19d76c7bc118d09fec45adc5370a1c5bf8067ca9f5557a4cf885fdb0fe0dcc9c3a7137226106fbc779a5 CHECKSIG VERIFY 1"]], +"010000000127587a10248001f424ad94bb55cd6cd6086a0e05767173bdbdf647187beca76c000000004948304502201b822ad10d6adc1a341ae8835be3f70a25201bbff31f59cbb9c5353a5f0eca18022100ea7b2f7074e9aa9cf70aa8d0ffee13e6b45dddabf1ab961bda378bcdb778fa4701ffffffff0100f2052a010000001976a914fc50c5907d86fed474ba5ce8b12a66e0a4c139d888ac00000000", true], + +["This is the nearly-standard transaction with CHECKSIGVERIFY 1 instead of CHECKSIG from tx_valid.json"], +["but with the signature duplicated in the scriptPubKey with a non-standard pushdata prefix"], +["See FindAndDelete, which will only remove if it uses the same pushdata prefix as is standard"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x4c 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true], + +["Same as above, but with the sig in the scriptSig also pushed with the same non-standard OP_PUSHDATA"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x4c 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006b4c473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true], + +["An invalid P2SH Transaction"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", true], + +["Tests for CheckTransaction()"], +["No inputs"], +["Skipped because this is not checked by btcscript, this is a problem for chain."], + +["No outputs"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x05ab9e14d983742513f0f451e105ffb4198d1dd4 EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022100f16703104aab4e4088317c862daec83440242411b039d14280e03dd33b487ab802201318a7be236672c5c56083eb7a5a195bc57a40af7923ff8545016cd3b571e2a601232103c40e5d339df3f30bf753e7e04450ae4ef76c9e45587d1d993bdc4cd06f0651c7acffffffff0000000000", true], + +["Negative output"], +["Removed because btcscript doesn't so tx sanity checking."], + +["MAX_MONEY + 1 output"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x32afac281462b822adbec5094b8d4d337dd5bd6a EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010140075af0750700015100000000", true], + +["MAX_MONEY output + 1 output"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xb558cbf4930954aa6a344363a15668d7477ae716 EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510001000000000000015100000000", true], + +["Duplicate inputs"], +["Removed because btcscript doesn't check input duplication, btcchain does"], + +["Coinbase of size 1"], +["Note the input is just required to make the tester happy"], +["Removed because btcscript dooesn't handle coinbase checking, btcchain does"], + +["Coinbase of size 101"], +["Note the input is just required to make the tester happy"], +["Removed because btcscript dooesn't handle coinbase checking, btcchain does"], + +["Null txin"], +["Removed because btcscript doesn't do tx sanity checking."], + +["Same as the transactions in valid with one input SIGHASH_ALL and one SIGHASH_ANYONECANPAY, but we set the _ANYONECANPAY sequence number, invalidating the SIGHASH_ALL signature"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"], + ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]], + "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df10101000000000200000000000000000000000000000000000000000000000000000000000000000000484730440220201dc2d030e380e8f9cfb41b442d930fa5a685bb2c8db5906671f865507d0670022018d9e7a8d4c8d86a73c2a724ee38ef983ec249827e0e464841735955c707ece98101000000010100000000000000015100000000", true], + +["Incorrect signature order"], +["Note the input is just required to make the tester happy"], +[[["b3da01dd4aae683c7aee4d5d8b52a540a508e1115f77cd7fa9a291243f501223", 0, "HASH160 0x14 0xb1ce99298d5f07364b57b1e5c9cc00be0b04a954 EQUAL"]], +"01000000012312503f2491a2a97fcd775f11e108a540a5528b5d4dee7a3c68ae4add01dab300000000fdfe000048304502207aacee820e08b0b174e248abd8d7a34ed63b5da3abedb99934df9fddd65c05c4022100dfe87896ab5ee3df476c2655f9fbe5bd089dccbef3e4ea05b5d121169fe7f5f401483045022100f6649b0eddfdfd4ad55426663385090d51ee86c3481bdc6b0c18ea6c0ece2c0b0220561c315b07cffa6f7dd9df96dbae9200c2dee09bf93cc35ca05e6cdf613340aa014c695221031d11db38972b712a9fe1fc023577c7ae3ddb4a3004187d41c45121eecfdbb5b7210207ec36911b6ad2382860d32989c7b8728e9489d7bbc94a6b5509ef0029be128821024ea9fac06f666a4adc3fc1357b7bec1fd0bdece2b9d08579226a8ebde53058e453aeffffffff0180380100000000001976a914c9b99cddf847d10685a4fabaa0baf505f7c3dfab88ac00000000", true], + +["Empty stack when we try to run CHECKSIG"], +[[["ad503f72c18df5801ee64d76090afe4c607fb2b822e9b7b63c5826c50e22fc3b", 0, "0x21 0x027c3a97665bf283a102a587a62a30a0c102d4d3b141015e2cae6f64e2543113e5 CHECKSIG NOT"]], +"01000000013bfc220ec526583cb6b7e922b8b27f604cfe0a09764de61e80f58dc1723f50ad0000000000ffffffff0101000000000000002321027c3a97665bf283a102a587a62a30a0c102d4d3b141015e2cae6f64e2543113e5ac00000000", true], + +["Make diffs cleaner by leaving a comment here without comma at the end"] +] diff --git a/data/tx_valid.json b/data/tx_valid.json new file mode 100644 index 00000000..c206f7a7 --- /dev/null +++ b/data/tx_valid.json @@ -0,0 +1,122 @@ +[ +["The following are deserialized transactions which are valid."], +["They are in the form"], +["[[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], +["serializedTransaction, enforceP2SH]"], +["Objects that are only a single string (like this one) are ignored"], + +["The following is 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], +["It is of particular interest because it contains an invalidly-encoded signature which OpenSSL accepts"], +["See http://r6.ca/blog/20111119T211504Z.html"], +["It is also the first OP_CHECKMULTISIG transaction in standard form"], +[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000490047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", true], + +["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], +["It has an arbitrary extra byte stuffed into the signature at pos length - 2"], +[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004A0048304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2bab01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", true], + +["The following is c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73"], +["It is of interest because it contains a 0-sequence as well as a signature of SIGHASH type 0 (which is not a real type)"], +[[["406b2b06bcd34d3c8733e6b79f7a394c8a431fbf4ff5ac705c93f4076bb77602", 0, "DUP HASH160 0x14 0xdc44b1164188067c3a32d4780f5996fa14a4f2d9 EQUALVERIFY CHECKSIG"]], +"01000000010276b76b07f4935c70acf54fbf1f438a4c397a9fb7e633873c4dd3bc062b6b40000000008c493046022100d23459d03ed7e9511a47d13292d3430a04627de6235b6e51a40f9cd386f2abe3022100e7d25b080f0bb8d8d5f878bba7d54ad2fda650ea8d158a33ee3cbd11768191fd004104b0e2c879e4daf7b9ab68350228c159766676a14f5815084ba166432aab46198d4cca98fa3e9981d0a90b2effc514b76279476550ba3663fdcaff94c38420e9d5000000000100093d00000000001976a9149a7b0f3b80c6baaeedce0a0842553800f832ba1f88ac00000000", true], + +["A nearly-standard transaction with CHECKSIGVERIFY 1 instead of CHECKSIG"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true], + +["Same as above, but with the signature duplicated in the scriptPubKey with the proper pushdata prefix"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true], + +["The following is f7fdd091fa6d8f5e7a8c2458f5c38faffff2d3f1406b6e4fe2c99dcc0d2d1cbb"], +["It caught a bug in the workaround for 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63 in an overly simple implementation"], +[[["b464e85df2a238416f8bdae11d120add610380ea07f4ef19c5f9dfd472f96c3d", 0, "DUP HASH160 0x14 0xbef80ecf3a44500fda1bc92176e442891662aed2 EQUALVERIFY CHECKSIG"], +["b7978cc96e59a8b13e0865d3f95657561a7f725be952438637475920bac9eb21", 1, "DUP HASH160 0x14 0xbef80ecf3a44500fda1bc92176e442891662aed2 EQUALVERIFY CHECKSIG"]], +"01000000023d6cf972d4dff9c519eff407ea800361dd0a121de1da8b6f4138a2f25de864b4000000008a4730440220ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e022049cffa1cdc102a0b56e0e04913606c70af702a1149dc3b305ab9439288fee090014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff21ebc9ba20594737864352e95b727f1a565756f9d365083eb1a8596ec98c97b7010000008a4730440220503ff10e9f1e0de731407a4a245531c9ff17676eda461f8ceeb8c06049fa2c810220c008ac34694510298fa60b3f000df01caa244f165b727d4896eb84f81e46bcc4014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff01f0da5200000000001976a914857ccd42dded6df32949d4646dfa10a92458cfaa88ac00000000", true], + +["The following tests for the presence of a bug in the handling of SIGHASH_SINGLE"], +["It results in signing the constant 1, instead of something generated based on the transaction,"], +["when the input doing the signing has an index greater than the maximum output index"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0xe52b482f2faa8ecbf0db344f93c84ac908557f33 EQUALVERIFY CHECKSIG"], ["0000000000000000000000000000000000000000000000000000000000000200", 0, "1"]], +"01000000020002000000000000000000000000000000000000000000000000000000000000000000000151ffffffff0001000000000000000000000000000000000000000000000000000000000000000000006b483045022100c9cdd08798a28af9d1baf44a6c77bcc7e279f47dc487c8c899911bc48feaffcc0220503c5c50ae3998a733263c5c0f7061b483e2b56c4c41b456e7d2f5a78a74c077032102d5c25adb51b61339d2b05315791e21bbe80ea470a49db0135720983c905aace0ffffffff010000000000000000015100000000", true], + +["An invalid P2SH Transaction"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", false], + +["A valid P2SH Transaction using the standard transaction type put forth in BIP 16"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x8febbed40483661de6958d957412f82deed8e2f7 EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100c66c9cdf4c43609586d15424c54707156e316d88b0a1534c9e6b0d4f311406310221009c0fe51dbc9c4ab7cc25d3fdbeccf6679fe6827f08edf2b4a9f16ee3eb0e438a0123210338e8034509af564c62644c07691942e0c056752008a173c89f60ab2a88ac2ebfacffffffff010000000000000000015100000000", true], + +["Tests for CheckTransaction()"], +["MAX_MONEY output"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x32afac281462b822adbec5094b8d4d337dd5bd6a EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010040075af0750700015100000000", true], + +["MAX_MONEY output + 0 output"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xb558cbf4930954aa6a344363a15668d7477ae716 EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510000000000000000015100000000", true], + +["Coinbase of size 2"], +["Note the input is just required to make the tester happy"], +[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]], +"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff025151ffffffff010000000000000000015100000000", true], + +["Coinbase of size 100"], +["Note the input is just required to make the tester happy"], +[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]], +"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6451515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151ffffffff010000000000000000015100000000", true], + +["Simple transaction with first input is signed with SIGHASH_ALL, second with SIGHASH_ANYONECANPAY"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"], + ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]], + "010000000200010000000000000000000000000000000000000000000000000000000000000000000049483045022100d180fd2eb9140aeb4210c9204d3f358766eb53842b2a9473db687fa24b12a3cc022079781799cd4f038b85135bbe49ec2b57f306b2bb17101b17f71f000fcab2b6fb01ffffffff0002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", true], + +["Same as above, but we change the sequence number of the first input to check that SIGHASH_ANYONECANPAY is being followed"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"], + ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]], + "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df101010000000002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", true], + +["afd9c17f8913577ec3509520bd6e5d63e9c0fd2a5f70c787993b097ba6ca9fae which has several SIGHASH_SINGLE signatures"], +[[["63cfa5a09dc540bf63e53713b82d9ea3692ca97cd608c384f2aa88e51a0aac70", 0, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"], + ["04e8d0fcf3846c6734477b98f0f3d4badfb78f020ee097a0be5fe347645b817d", 1, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"], + ["ee1377aff5d0579909e11782e1d2f5f7b84d26537be7f5516dd4e43373091f3f", 1, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"]], + "010000000370ac0a1ae588aaf284c308d67ca92c69a39e2db81337e563bf40c59da0a5cf63000000006a4730440220360d20baff382059040ba9be98947fd678fb08aab2bb0c172efa996fd8ece9b702201b4fb0de67f015c90e7ac8a193aeab486a1f587e0f54d0fb9552ef7f5ce6caec032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff7d815b6447e35fbea097e00e028fb7dfbad4f3f0987b4734676c84f3fcd0e804010000006b483045022100c714310be1e3a9ff1c5f7cacc65c2d8e781fc3a88ceb063c6153bf950650802102200b2d0979c76e12bb480da635f192cc8dc6f905380dd4ac1ff35a4f68f462fffd032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff3f1f097333e4d46d51f5e77b53264db8f7f5d2e18217e1099957d0f5af7713ee010000006c493046022100b663499ef73273a3788dea342717c2640ac43c5a1cf862c9e09b206fcb3f6bb8022100b09972e75972d9148f2bdd462e5cb69b57c1214b88fc55ca638676c07cfc10d8032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff0380841e00000000001976a914bfb282c70c4191f45b5a6665cad1682f2c9cfdfb88ac80841e00000000001976a9149857cc07bed33a5cf12b9c5e0500b675d500c81188ace0fd1c00000000001976a91443c52850606c872403c0601e69fa34b26f62db4a88ac00000000", true], + + ["ddc454a1c0c35c188c98976b17670f69e586d9c0f3593ea879928332f0a069e7, which spends an input that pushes using a PUSHDATA1 that is negative when read as signed"], + [[["c5510a5dd97a25f43175af1fe649b707b1df8e1a41489bac33a23087027a2f48", 0, "0x4c 0xae 0x606563686f2022553246736447566b58312b5a536e587574356542793066794778625456415675534a6c376a6a334878416945325364667657734f53474f36633338584d7439435c6e543249584967306a486956304f376e775236644546673d3d22203e20743b206f70656e73736c20656e63202d7061737320706173733a5b314a564d7751432d707269766b65792d6865785d202d64202d6165732d3235362d636263202d61202d696e207460 DROP DUP HASH160 0x14 0xbfd7436b6265aa9de506f8a994f881ff08cc2872 EQUALVERIFY CHECKSIG"]], + "0100000001482f7a028730a233ac9b48411a8edfb107b749e61faf7531f4257ad95d0a51c5000000008b483045022100bf0bbae9bde51ad2b222e87fbf67530fbafc25c903519a1e5dcc52a32ff5844e022028c4d9ad49b006dd59974372a54291d5764be541574bb0c4dc208ec51f80b7190141049dd4aad62741dc27d5f267f7b70682eee22e7e9c1923b9c0957bdae0b96374569b460eb8d5b40d972e8c7c0ad441de3d94c4a29864b212d56050acb980b72b2bffffffff0180969800000000001976a914e336d0017a9d28de99d16472f6ca6d5a3a8ebc9988ac00000000", true], + +["Correct signature order"], +["Note the input is just required to make the tester happy"], +[[["b3da01dd4aae683c7aee4d5d8b52a540a508e1115f77cd7fa9a291243f501223", 0, "HASH160 0x14 0xb1ce99298d5f07364b57b1e5c9cc00be0b04a954 EQUAL"]], +"01000000012312503f2491a2a97fcd775f11e108a540a5528b5d4dee7a3c68ae4add01dab300000000fdfe0000483045022100f6649b0eddfdfd4ad55426663385090d51ee86c3481bdc6b0c18ea6c0ece2c0b0220561c315b07cffa6f7dd9df96dbae9200c2dee09bf93cc35ca05e6cdf613340aa0148304502207aacee820e08b0b174e248abd8d7a34ed63b5da3abedb99934df9fddd65c05c4022100dfe87896ab5ee3df476c2655f9fbe5bd089dccbef3e4ea05b5d121169fe7f5f4014c695221031d11db38972b712a9fe1fc023577c7ae3ddb4a3004187d41c45121eecfdbb5b7210207ec36911b6ad2382860d32989c7b8728e9489d7bbc94a6b5509ef0029be128821024ea9fac06f666a4adc3fc1357b7bec1fd0bdece2b9d08579226a8ebde53058e453aeffffffff0180380100000000001976a914c9b99cddf847d10685a4fabaa0baf505f7c3dfab88ac00000000", true], + +["cc60b1f899ec0a69b7c3f25ddf32c4524096a9c5b01cbd84c6d0312a0c478984, which is a fairly strange transaction which relies on OP_CHECKSIG returning 0 when checking a completely invalid sig of length 0"], +[[["cbebc4da731e8995fe97f6fadcd731b36ad40e5ecb31e38e904f6e5982fa09f7", 0, "0x2102085c6600657566acc2d6382a47bc3f324008d2aa10940dd7705a48aa2a5a5e33ac7c2103f5d0fb955f95dd6be6115ce85661db412ec6a08abcbfce7da0ba8297c6cc0ec4ac7c5379a820d68df9e32a147cffa36193c6f7c43a1c8c69cda530e1c6db354bfabdcfefaf3c875379a820f531f3041d3136701ea09067c53e7159c8f9b2746a56c3d82966c54bbc553226879a5479827701200122a59a5379827701200122a59a6353798277537982778779679a68"]], +"0100000001f709fa82596e4f908ee331cb5e0ed46ab331d7dcfaf697fe95891e73dac4ebcb000000008c20ca42095840735e89283fec298e62ac2ddea9b5f34a8cbb7097ad965b87568100201b1b01dc829177da4a14551d2fc96a9db00c6501edfa12f22cd9cefd335c227f483045022100a9df60536df5733dd0de6bc921fab0b3eee6426501b43a228afa2c90072eb5ca02201c78b74266fac7d1db5deff080d8a403743203f109fbcabf6d5a760bf87386d20100ffffffff01c075790000000000232103611f9a45c18f28f06f19076ad571c344c82ce8fcfe34464cf8085217a2d294a6ac00000000", true], + +["Empty pubkey"], +[[["229257c295e7f555421c1bfec8538dd30a4b5c37c1c8810bbe83cafa7811652c", 0, "0x00 CHECKSIG NOT"]], +"01000000012c651178faca83be0b81c8c1375c4b0ad38d53c8fe1b1c4255f5e795c25792220000000049483045022100d6044562284ac76c985018fc4a90127847708c9edb280996c507b28babdc4b2a02203d74eca3f1a4d1eea7ff77b528fde6d5dc324ec2dbfdb964ba885f643b9704cd01ffffffff010100000000000000232102c2410f8891ae918cab4ffc4bb4a3b0881be67c7a1e7faa8b5acf9ab8932ec30cac00000000", true], + +["Empty signature"], +[[["9ca93cfd8e3806b9d9e2ba1cf64e3cc6946ee0119670b1796a09928d14ea25f7", 0, "0x21 0x028a1d66975dbdf97897e3a4aef450ebeb5b5293e4a0b4a6d3a2daaa0b2b110e02 CHECKSIG NOT"]], +"0100000001f725ea148d92096a79b1709611e06e94c63c4ef61cbae2d9b906388efd3ca99c000000000100ffffffff0101000000000000002321028a1d66975dbdf97897e3a4aef450ebeb5b5293e4a0b4a6d3a2daaa0b2b110e02ac00000000", true], + +[[["444e00ed7840d41f20ecd9c11d3f91982326c731a02f3c05748414a4fa9e59be", 0, "1 0x00 0x21 0x02136b04758b0b6e363e7a6fbe83aaf527a153db2b060d36cc29f7f8309ba6e458 2 CHECKMULTISIG"]], +"0100000001be599efaa4148474053c2fa031c7262398913f1dc1d9ec201fd44078ed004e44000000004900473044022022b29706cb2ed9ef0cb3c97b72677ca2dfd7b4160f7b4beb3ba806aa856c401502202d1e52582412eba2ed474f1f437a427640306fd3838725fab173ade7fe4eae4a01ffffffff010100000000000000232103ac4bba7e7ca3e873eea49e08132ad30c7f03640b6539e9b59903cf14fd016bbbac00000000", true], + +[[["e16abbe80bf30c080f63830c8dbf669deaef08957446e95940227d8c5e6db612", 0, "1 0x21 0x03905380c7013e36e6e19d305311c1b81fce6581f5ee1c86ef0627c68c9362fc9f 0x00 2 CHECKMULTISIG"]], +"010000000112b66d5e8c7d224059e946749508efea9d66bf8d0c83630f080cf30be8bb6ae100000000490047304402206ffe3f14caf38ad5c1544428e99da76ffa5455675ec8d9780fac215ca17953520220779502985e194d84baa36b9bd40a0dbd981163fa191eb884ae83fc5bd1c86b1101ffffffff010100000000000000232103905380c7013e36e6e19d305311c1b81fce6581f5ee1c86ef0627c68c9362fc9fac00000000", true], + +[[["ebbcf4bfce13292bd791d6a65a2a858d59adbf737e387e40370d4e64cc70efb0", 0, "2 0x21 0x033bcaa0a602f0d44cc9d5637c6e515b0471db514c020883830b7cefd73af04194 0x21 0x03a88b326f8767f4f192ce252afe33c94d25ab1d24f27f159b3cb3aa691ffe1423 2 CHECKMULTISIG NOT"]], +"0100000001b0ef70cc644e0d37407e387e73bfad598d852a5aa6d691d72b2913cebff4bceb000000004a00473044022068cd4851fc7f9a892ab910df7a24e616f293bcb5c5fbdfbc304a194b26b60fba022078e6da13d8cb881a22939b952c24f88b97afd06b4c47a47d7f804c9a352a6d6d0100ffffffff0101000000000000002321033bcaa0a602f0d44cc9d5637c6e515b0471db514c020883830b7cefd73af04194ac00000000", true], + +[[["ba4cd7ae2ad4d4d13ebfc8ab1d93a63e4a6563f25089a18bf0fc68f282aa88c1", 0, "2 0x21 0x037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1 0x21 0x02edc823cd634f2c4033d94f5755207cb6b60c4b1f1f056ad7471c47de5f2e4d50 2 CHECKMULTISIG NOT"]], +"0100000001c188aa82f268fcf08ba18950f263654a3ea6931dabc8bf3ed1d4d42aaed74cba000000004b0000483045022100940378576e069aca261a6b26fb38344e4497ca6751bb10905c76bb689f4222b002204833806b014c26fd801727b792b1260003c55710f87c5adbd7a9cb57446dbc9801ffffffff0101000000000000002321037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1ac00000000", true], + +["Make diffs cleaner by leaving a comment here without comma at the end"] +] diff --git a/internal_test.go b/internal_test.go index 5ce611b3..ba299f0d 100644 --- a/internal_test.go +++ b/internal_test.go @@ -6,8 +6,16 @@ package btcscript import ( "crypto/ecdsa" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "github.com/conformal/btcutil" "github.com/conformal/btcwire" "io" + "io/ioutil" + "strconv" + "strings" "testing" ) @@ -3731,3 +3739,453 @@ func TestUnparsingInvalidOpcodes(t *testing.T) { } } } + +// parse hex string into a []byte. +func parseHex(tok string) ([]byte, error) { + if !strings.HasPrefix(tok, "0x") { + return nil, errors.New("not a hex number") + } + return hex.DecodeString(tok[2:]) +} + +// ParseShortForm parses a string as as used in the bitcoind reference tests +// into the script it came from. +func ParseShortForm(script string) ([]byte, error) { + ops := make(map[string]*opcode) + + // the format used for these tests is pretty simple if ad-hoc: + // - opcodes other than the push opcodes and unknown are present as + // either OP_NAME or just NAME + // - plain numbers are made into push operations + // - numbers beginning with 0x are inserted into the []byte as-is (so + // 0x14 is OP_DATA_20) + // - single quoted strings are pushed as data. + // - anything else is an error. + for _, op := range opcodemap { + if op.value < OP_NOP && op.value != OP_RESERVED { + continue + } + if strings.Contains(op.name, "OP_UNKNOWN") { + continue + } + ops[op.name] = op + ops[strings.TrimPrefix(op.name, "OP_")] = op + } + // do once, build map. + + // Split only does one separator so convert all \n and tab into space. + script = strings.Replace(script, "\n", " ", -1) + script = strings.Replace(script, "\t", " ", -1) + tokens := strings.Split(script, " ") + builder := NewScriptBuilder() + + for _, tok := range tokens { + if len(tok) == 0 { + continue + } + // if parses as a plain number + if num, err := strconv.ParseInt(tok, 10, 64); err == nil { + builder.AddInt64(num) + continue + } else if bts, err := parseHex(tok); err == nil { + // naughty... + builder.script = append(builder.script, bts...) + } else if len(tok) >= 2 && + tok[0] == '\'' && tok[len(tok)-1] == '\'' { + builder.AddData([]byte(tok[1 : len(tok)-1])) + } else if opcode, ok := ops[tok]; ok { + builder.AddOp(opcode.value) + } else { + return nil, fmt.Errorf("bad token \"%s\"", tok) + } + + } + return builder.Script(), nil +} + +func TestBitcoindInvalidTests(t *testing.T) { + file, err := ioutil.ReadFile("data/script_invalid.json") + if err != nil { + t.Errorf("TestBitcoindInvalidTests: %v\n", err) + return + } + + var tests [][]string + err = json.Unmarshal(file, &tests) + if err != nil { + t.Errorf("TestBitcoindInvalidTests couldn't Unmarshal: %v\n", + err) + return + } + tx := btcwire.NewMsgTx() + for x, test := range tests { + if len(test) < 2 && len(test) > 3 { + t.Errorf("TestBitcoindInvalidTests: invalid test #%d\n", + x) + continue + } + name := "" + if len(test) == 3 { + name = fmt.Sprintf("test (%s)", test[2]) + } else { + name = fmt.Sprintf("test ([%s, %s])", test[0], test[1]) + } + + scriptSig, err := ParseShortForm(test[0]) + if err != nil { + t.Errorf("%s: can't parse scriptSig; %v", name, err) + continue + } + + scriptPubKey, err := ParseShortForm(test[1]) + if err != nil { + t.Errorf("%s: can't parse scriptPubkey; %v", name, err) + continue + } + + s, err := NewScript(scriptSig, scriptPubKey, 0, tx, ScriptBip16) + if err == nil { + if err := s.Execute(); err == nil { + t.Errorf("%s test succeeded when it "+ + "should have failed\n", name) + } + continue + } + } +} + +func TestBitcoindValidTests(t *testing.T) { + file, err := ioutil.ReadFile("data/script_valid.json") + if err != nil { + t.Errorf("TestBitcoinValidTests: %v\n", err) + return + } + + var tests [][]string + err = json.Unmarshal(file, &tests) + if err != nil { + t.Errorf("TestBitcoindInvalidTests couldn't Unmarshal: %v\n", + err) + return + } + tx := btcwire.NewMsgTx() + for x, test := range tests { + if len(test) < 2 && len(test) > 3 { + t.Errorf("TestBitcoindInvalidTests: invalid test #%d\n", + x) + continue + } + name := "" + if len(test) == 3 { + name = fmt.Sprintf("test (%s)", test[2]) + } else { + name = fmt.Sprintf("test ([%s, %s])", test[0], test[1]) + } + + scriptSig, err := ParseShortForm(test[0]) + if err != nil { + t.Errorf("%s: can't parse scriptSig; %v", name, err) + continue + } + + scriptPubKey, err := ParseShortForm(test[1]) + if err != nil { + t.Errorf("%s: can't parse scriptPubkey; %v", name, err) + continue + } + + s, err := NewScript(scriptSig, scriptPubKey, 0, tx, ScriptBip16) + if err != nil { + t.Errorf("%s failed to create script: %v", name, err) + continue + } + + err = s.Execute() + if err != nil { + t.Errorf("%s failed to execute: %v", name, err) + continue + } + } +} + +func TestBitcoindTxValidTests(t *testing.T) { + file, err := ioutil.ReadFile("data/tx_valid.json") + if err != nil { + t.Errorf("TestBitcoindInvalidTests: %v\n", err) + return + } + + var tests [][]interface{} + err = json.Unmarshal(file, &tests) + if err != nil { + t.Errorf("TestBitcoindInvalidTests couldn't Unmarshal: %v\n", + err) + return + } + + // for ma is eaitehr a ["this is a comment "] + // or [[[previous hash, previous index, previous scripbPubKey]...,] + // serializedTransaction, enforceP2SH] +testloop: + for i, test := range tests { + inputs, ok := test[0].([]interface{}) + if !ok { + continue + } + + if len(test) != 3 { + t.Errorf("bad test (bad lenggh) %d: %v", i, test) + continue + + } + serializedhex, ok := test[1].(string) + if !ok { + t.Errorf("bad test (arg 2 not string) %d: %v", i, test) + continue + } + serializedTx, err := hex.DecodeString(serializedhex) + if err != nil { + t.Errorf("bad test (arg 2 not hex %v) %d: %v", err, i, + test) + continue + } + + tx, err := btcutil.NewTxFromBytes(serializedTx) + if err != nil { + t.Errorf("bad test (arg 2 not msgtx %v) %d: %v", err, + i, test) + continue + } + + enforceP2SH, ok := test[2].(bool) + if !ok { + t.Errorf("bad test (arg 3 not bool) %d: %v", i, test) + continue + } + + var flags ScriptFlags + if enforceP2SH { + flags |= ScriptBip16 + } + + prevOuts := make(map[btcwire.OutPoint][]byte) + for j, iinput := range inputs { + input, ok := iinput.([]interface{}) + if !ok { + t.Errorf("bad test (%dth input not array)"+ + "%d: %v", j, i, test) + continue + } + + if len(input) != 3 { + t.Errorf("bad test (%dth input wrong length)"+ + "%d: %v", j, i, test) + continue + } + + previoustx, ok := input[0].(string) + if !ok { + t.Errorf("bad test (%dth input sha not string)"+ + "%d: %v", j, i, test) + continue + } + + prevhash, err := btcwire.NewShaHashFromStr(previoustx) + if err != nil { + t.Errorf("bad test (%dth input sha not sha %v)"+ + "%d: %v", j, err, i, test) + continue + } + + idxf, ok := input[1].(float64) + if !ok { + t.Errorf("bad test (%dth input idx not number)"+ + "%d: %v", j, i, test) + continue + } + + idx := uint32(idxf) // (floor(idxf) == idxf?) + + oscript, ok := input[2].(string) + if !ok { + t.Errorf("bad test (%dth input script not "+ + "string) %d: %v", j, i, test) + continue + } + + script, err := ParseShortForm(oscript) + if err != nil { + t.Errorf("bad test (%dth input script doesn't "+ + "parse %v) %d: %v", j, err, i, test) + continue + } + + prevOuts[*btcwire.NewOutPoint(prevhash, idx)] = script + } + + for k, txin := range tx.MsgTx().TxIn { + pkScript, ok := prevOuts[txin.PreviousOutpoint] + if !ok { + t.Errorf("bad test (missing %dth input) %d:%v", + k, i, test) + continue testloop + } + s, err := NewScript(txin.SignatureScript, pkScript, k, + tx.MsgTx(), flags) + if err != nil { + t.Errorf("test (%d:%v:%d) failed to create "+ + "script: %v", i, test, k, err) + continue + } + + err = s.Execute() + if err != nil { + t.Errorf("test (%d:%v:%d) failed to execute: "+ + "%v", i, test, k, err) + continue + } + } + } +} + +func TestBitcoindTxInvalidTests(t *testing.T) { + file, err := ioutil.ReadFile("data/tx_invalid.json") + if err != nil { + t.Errorf("TestBitcoindInvalidTests: %v\n", err) + return + } + + var tests [][]interface{} + err = json.Unmarshal(file, &tests) + if err != nil { + t.Errorf("TestBitcoindInvalidTests couldn't Unmarshal: %v\n", + err) + return + } + + // for ma is eaitehr a ["this is a comment "] + // or [[[previous hash, previous index, previous scripbPubKey]...,] + // serializedTransaction, enforceP2SH] +testloop: + for i, test := range tests { + inputs, ok := test[0].([]interface{}) + if !ok { + continue + } + + if len(test) != 3 { + t.Errorf("bad test (bad lenggh) %d: %v", i, test) + continue + + } + serializedhex, ok := test[1].(string) + if !ok { + t.Errorf("bad test (arg 2 not string) %d: %v", i, test) + continue + } + serializedTx, err := hex.DecodeString(serializedhex) + if err != nil { + t.Errorf("bad test (arg 2 not hex %v) %d: %v", err, i, + test) + continue + } + + tx, err := btcutil.NewTxFromBytes(serializedTx) + if err != nil { + t.Errorf("bad test (arg 2 not msgtx %v) %d: %v", err, + i, test) + continue + } + + enforceP2SH, ok := test[2].(bool) + if !ok { + t.Errorf("bad test (arg 3 not bool) %d: %v", i, test) + continue + } + + var flags ScriptFlags + if enforceP2SH { + flags |= ScriptBip16 + } + + prevOuts := make(map[btcwire.OutPoint][]byte) + for j, iinput := range inputs { + input, ok := iinput.([]interface{}) + if !ok { + t.Errorf("bad test (%dth input not array)"+ + "%d: %v", j, i, test) + continue testloop + } + + if len(input) != 3 { + t.Errorf("bad test (%dth input wrong length)"+ + "%d: %v", j, i, test) + continue testloop + } + + previoustx, ok := input[0].(string) + if !ok { + t.Errorf("bad test (%dth input sha not string)"+ + "%d: %v", j, i, test) + continue testloop + } + + prevhash, err := btcwire.NewShaHashFromStr(previoustx) + if err != nil { + t.Errorf("bad test (%dth input sha not sha %v)"+ + "%d: %v", j, err, i, test) + continue testloop + } + + idxf, ok := input[1].(float64) + if !ok { + t.Errorf("bad test (%dth input idx not number)"+ + "%d: %v", j, i, test) + continue testloop + } + + idx := uint32(idxf) // (floor(idxf) == idxf?) + + oscript, ok := input[2].(string) + if !ok { + t.Errorf("bad test (%dth input script not "+ + "string) %d: %v", j, i, test) + continue testloop + } + + script, err := ParseShortForm(oscript) + if err != nil { + t.Errorf("bad test (%dth input script doesn't "+ + "parse %v) %d: %v", j, err, i, test) + continue testloop + } + + prevOuts[*btcwire.NewOutPoint(prevhash, idx)] = script + } + + for k, txin := range tx.MsgTx().TxIn { + pkScript, ok := prevOuts[txin.PreviousOutpoint] + if !ok { + t.Errorf("bad test (missing %dth input) %d:%v", + k, i, test) + continue testloop + } + // These are meant to fail, so as soon as the first + // input fails the transaction has failed. (some of the + // test txns have good inputs, too.. + s, err := NewScript(txin.SignatureScript, pkScript, k, + tx.MsgTx(), flags) + if err != nil { + continue testloop + } + + err = s.Execute() + if err != nil { + continue testloop + } + + } + t.Errorf("test (%d:%v) succeeded when should fail", + i, test) + } +} diff --git a/test_coverage.txt b/test_coverage.txt index 2105107b..51ea818b 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -1,170 +1,171 @@ -github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 100.00% (58/58) +github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 100.00% (60/60) +github.com/conformal/btcscript/script.go Script.Step 100.00% (37/37) +github.com/conformal/btcscript/opcode.go opcodeCheckSig 100.00% (29/29) github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (29/29) github.com/conformal/btcscript/address.go ExtractPkScriptAddrs 100.00% (27/27) github.com/conformal/btcscript/script.go CalcScriptInfo 100.00% (25/25) +github.com/conformal/btcscript/script.go NewScript 100.00% (23/23) github.com/conformal/btcscript/stack.go asInt 100.00% (23/23) github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddData 100.00% (22/22) github.com/conformal/btcscript/opcode.go parsedOpcode.disabled 100.00% (17/17) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (16/16) -github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (15/15) github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (15/15) +github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (15/15) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) -github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (13/13) -github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) -github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) -github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) -github.com/conformal/btcscript/script.go PayToAddrScript 100.00% (11/11) -github.com/conformal/btcscript/script.go typeOfScript 100.00% (11/11) +github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (13/13) +github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) +github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) +github.com/conformal/btcscript/script.go typeOfScript 100.00% (11/11) +github.com/conformal/btcscript/script.go PayToAddrScript 100.00% (11/11) +github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) -github.com/conformal/btcscript/script.go Script.CheckErrorCondition 100.00% (9/9) -github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) -github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) +github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/script.go Script.CheckErrorCondition 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) +github.com/conformal/btcscript/script.go Script.Execute 100.00% (8/8) github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) github.com/conformal/btcscript/script.go MultiSigScript 100.00% (8/8) -github.com/conformal/btcscript/script.go Script.Execute 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddInt64 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddUint64 100.00% (7/7) github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddUint64 100.00% (7/7) -github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) +github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodePick 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodePick 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) -github.com/conformal/btcscript/script.go getStack 100.00% (4/4) -github.com/conformal/btcscript/script.go isNullData 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) -github.com/conformal/btcscript/opcode.go parsedOpcode.alwaysIllegal 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) +github.com/conformal/btcscript/script.go isNullData 100.00% (4/4) github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) -github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) -github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) -github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/script.go getStack 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) +github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) +github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) -github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) -github.com/conformal/btcscript/script.go isSmallInt 100.00% (3/3) +github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) +github.com/conformal/btcscript/opcode.go parsedOpcode.alwaysIllegal 100.00% (4/4) +github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) github.com/conformal/btcscript/script.go ScriptClass.String 100.00% (3/3) -github.com/conformal/btcscript/script.go setStack 100.00% (3/3) +github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) github.com/conformal/btcscript/script.go asSmallInt 100.00% (3/3) -github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) -github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/conformal/btcscript/script.go setStack 100.00% (3/3) +github.com/conformal/btcscript/script.go isSmallInt 100.00% (3/3) +github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Reset 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) +github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddOp 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) -github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Reset 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) -github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) -github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) -github.com/conformal/btcscript/log.go init 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) +github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) +github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) +github.com/conformal/btcscript/log.go init 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) -github.com/conformal/btcscript/scriptbuilder.go NewScriptBuilder 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) +github.com/conformal/btcscript/script.go payToPubKeyHashScript 100.00% (1/1) +github.com/conformal/btcscript/script.go payToScriptHashScript 100.00% (1/1) +github.com/conformal/btcscript/script.go payToPubKeyScript 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) +github.com/conformal/btcscript/scriptbuilder.go NewScriptBuilder 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) github.com/conformal/btcscript/opcode.go init 100.00% (1/1) github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) -github.com/conformal/btcscript/script.go payToPubKeyHashScript 100.00% (1/1) -github.com/conformal/btcscript/script.go payToScriptHashScript 100.00% (1/1) -github.com/conformal/btcscript/script.go payToPubKeyScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) -github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.Step 97.30% (36/37) -github.com/conformal/btcscript/script.go NewScript 95.65% (22/23) -github.com/conformal/btcscript/opcode.go opcodeCheckSig 93.10% (27/29) -github.com/conformal/btcscript/script.go expectedInputs 85.71% (6/7) +github.com/conformal/btcscript/script.go calcScriptHash 97.44% (38/39) +github.com/conformal/btcscript/script.go canonicalPush 92.86% (13/14) github.com/conformal/btcscript/script.go unparseScript 85.71% (6/7) -github.com/conformal/btcscript/script.go calcScriptHash 82.05% (32/39) -github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4) +github.com/conformal/btcscript/script.go expectedInputs 85.71% (6/7) github.com/conformal/btcscript/script.go IsPushOnlyScript 75.00% (3/4) -github.com/conformal/btcscript/script.go HasCanonicalPushes 66.67% (12/18) +github.com/conformal/btcscript/script.go HasCanonicalPushes 71.43% (5/7) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/10) github.com/conformal/btcscript/script.go CalcMultiSigStats 0.00% (0/8) -github.com/conformal/btcscript/script.go @566:34 0.00% (0/6) -github.com/conformal/btcscript/script.go @554:34 0.00% (0/4) -github.com/conformal/btcscript/script.go @599:34 0.00% (0/3) -github.com/conformal/btcscript/opcode.go opcodeDisabled 0.00% (0/1) +github.com/conformal/btcscript/script.go @577:34 0.00% (0/6) +github.com/conformal/btcscript/script.go @565:34 0.00% (0/4) +github.com/conformal/btcscript/script.go @610:34 0.00% (0/3) github.com/conformal/btcscript/log.go UseLogger 0.00% (0/1) -github.com/conformal/btcscript/opcode.go @1803:33 0.00% (0/1) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript --------------------------- 94.95% (1054/1110) +github.com/conformal/btcscript/opcode.go @1803:33 0.00% (0/1) +github.com/conformal/btcscript/opcode.go opcodeDisabled 0.00% (0/1) +github.com/conformal/btcscript --------------------------- 96.23% (1073/1115) From f529a37123efa587f90c1147c4d847fcd077b5ab Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 3 Apr 2014 17:10:36 -0500 Subject: [PATCH 123/174] Add tests for doing math on 5-byte ints. This commit addes a couple of tests to ensure performing math operations on a 5-byte integer, even if the result is a 4-byte integer, is considered invalid. --- data/script_invalid.json | 2 + test_coverage.txt | 208 +++++++++++++++++++-------------------- 2 files changed, 104 insertions(+), 106 deletions(-) diff --git a/data/script_invalid.json b/data/script_invalid.json index 761cc4a0..4bc36133 100644 --- a/data/script_invalid.json +++ b/data/script_invalid.json @@ -258,6 +258,8 @@ ["2147483648", "1ADD 1", "We cannot do math on 5-byte integers"], ["-2147483648", "1ADD 1", "Because we use a sign bit, -2147483648 is also 5 bytes"], +["2147483647", "1ADD 1SUB 1", "We cannot do math on 5-byte integers, even if the result is 4-bytes"], +["2147483648", "1SUB 1", "We cannot do math on 5-byte integers, even if the result is 4-bytes"], ["1", "1 ENDIF", "ENDIF without IF"], ["1", "IF 1", "IF without ENDIF"], diff --git a/test_coverage.txt b/test_coverage.txt index 51ea818b..d98c67a6 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -1,171 +1,167 @@ github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 100.00% (60/60) -github.com/conformal/btcscript/script.go Script.Step 100.00% (37/37) -github.com/conformal/btcscript/opcode.go opcodeCheckSig 100.00% (29/29) +github.com/conformal/btcscript/script.go Script.Step 100.00% (36/36) github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (29/29) github.com/conformal/btcscript/address.go ExtractPkScriptAddrs 100.00% (27/27) github.com/conformal/btcscript/script.go CalcScriptInfo 100.00% (25/25) -github.com/conformal/btcscript/script.go NewScript 100.00% (23/23) github.com/conformal/btcscript/stack.go asInt 100.00% (23/23) github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddData 100.00% (22/22) +github.com/conformal/btcscript/script.go NewScript 100.00% (23/23) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddData 100.00% (19/19) github.com/conformal/btcscript/opcode.go parsedOpcode.disabled 100.00% (17/17) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (16/16) -github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (15/15) github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (15/15) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) -github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) -github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (13/13) -github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) +github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (14/14) github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) +github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) +github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) +github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (12/12) +github.com/conformal/btcscript/script.go PayToAddrScript 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) -github.com/conformal/btcscript/script.go typeOfScript 100.00% (11/11) -github.com/conformal/btcscript/script.go PayToAddrScript 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) +github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) -github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) -github.com/conformal/btcscript/script.go Script.CheckErrorCondition 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) -github.com/conformal/btcscript/script.go Script.Execute 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) github.com/conformal/btcscript/script.go MultiSigScript 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddInt64 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddUint64 100.00% (7/7) -github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) +github.com/conformal/btcscript/script.go typeOfScript 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) -github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) +github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddInt64 100.00% (7/7) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddUint64 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodePick 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodePick 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) +github.com/conformal/btcscript/opcode.go parsedOpcode.alwaysIllegal 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) +github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) +github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) github.com/conformal/btcscript/script.go isNullData 100.00% (4/4) github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/script.go getStack 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) -github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) -github.com/conformal/btcscript/opcode.go parsedOpcode.alwaysIllegal 100.00% (4/4) -github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) -github.com/conformal/btcscript/script.go ScriptClass.String 100.00% (3/3) -github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) -github.com/conformal/btcscript/script.go asSmallInt 100.00% (3/3) +github.com/conformal/btcscript/script.go getStack 100.00% (4/4) github.com/conformal/btcscript/script.go setStack 100.00% (3/3) github.com/conformal/btcscript/script.go isSmallInt 100.00% (3/3) -github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) -github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) +github.com/conformal/btcscript/script.go asSmallInt 100.00% (3/3) +github.com/conformal/btcscript/script.go ScriptClass.String 100.00% (3/3) +github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) -github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddOp 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Reset 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) -github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Reset 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) +github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) +github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) -github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) -github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) github.com/conformal/btcscript/log.go init 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) +github.com/conformal/btcscript/scriptbuilder.go NewScriptBuilder 100.00% (1/1) +github.com/conformal/btcscript/opcode.go init 100.00% (1/1) +github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) github.com/conformal/btcscript/script.go payToPubKeyHashScript 100.00% (1/1) github.com/conformal/btcscript/script.go payToScriptHashScript 100.00% (1/1) github.com/conformal/btcscript/script.go payToPubKeyScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) -github.com/conformal/btcscript/scriptbuilder.go NewScriptBuilder 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) -github.com/conformal/btcscript/opcode.go init 100.00% (1/1) -github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) +github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) +github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) github.com/conformal/btcscript/script.go calcScriptHash 97.44% (38/39) +github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.67% (29/30) github.com/conformal/btcscript/script.go canonicalPush 92.86% (13/14) github.com/conformal/btcscript/script.go unparseScript 85.71% (6/7) github.com/conformal/btcscript/script.go expectedInputs 85.71% (6/7) +github.com/conformal/btcscript/script.go Script.CheckErrorCondition 75.00% (9/12) github.com/conformal/btcscript/script.go IsPushOnlyScript 75.00% (3/4) github.com/conformal/btcscript/script.go HasCanonicalPushes 71.43% (5/7) +github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/10) github.com/conformal/btcscript/script.go CalcMultiSigStats 0.00% (0/8) -github.com/conformal/btcscript/script.go @577:34 0.00% (0/6) -github.com/conformal/btcscript/script.go @565:34 0.00% (0/4) -github.com/conformal/btcscript/script.go @610:34 0.00% (0/3) github.com/conformal/btcscript/log.go UseLogger 0.00% (0/1) -github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript/opcode.go @1803:33 0.00% (0/1) github.com/conformal/btcscript/opcode.go opcodeDisabled 0.00% (0/1) -github.com/conformal/btcscript --------------------------- 96.23% (1073/1115) +github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) +github.com/conformal/btcscript --------------------------- 96.20% (1063/1105) From 4fce6d1476ea32bafb5d535f0e68910ca9524705 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 3 Apr 2014 23:18:29 -0500 Subject: [PATCH 124/174] Sync latest script tests to bitcoind test suite. --- data/script_invalid.json | 1 + data/script_valid.json | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/data/script_invalid.json b/data/script_invalid.json index 4bc36133..cbdb1a3f 100644 --- a/data/script_invalid.json +++ b/data/script_invalid.json @@ -257,6 +257,7 @@ ["1","0xba", "0xba == OP_NOP10 + 1"], ["2147483648", "1ADD 1", "We cannot do math on 5-byte integers"], +["2147483648", "NEGATE 1", "We cannot do math on 5-byte integers"], ["-2147483648", "1ADD 1", "Because we use a sign bit, -2147483648 is also 5 bytes"], ["2147483647", "1ADD 1SUB 1", "We cannot do math on 5-byte integers, even if the result is 4-bytes"], ["2147483648", "1SUB 1", "We cannot do math on 5-byte integers, even if the result is 4-bytes"], diff --git a/data/script_valid.json b/data/script_valid.json index e4c181ca..6313e67b 100644 --- a/data/script_valid.json +++ b/data/script_valid.json @@ -97,6 +97,9 @@ ["8388608", "SIZE 4 EQUAL"], ["2147483647", "SIZE 4 EQUAL"], ["2147483648", "SIZE 5 EQUAL"], +["549755813887", "SIZE 5 EQUAL"], +["549755813888", "SIZE 6 EQUAL"], +["9223372036854775807", "SIZE 8 EQUAL"], ["-1", "SIZE 1 EQUAL"], ["-127", "SIZE 1 EQUAL"], ["-128", "SIZE 2 EQUAL"], @@ -106,6 +109,9 @@ ["-8388608", "SIZE 4 EQUAL"], ["-2147483647", "SIZE 4 EQUAL"], ["-2147483648", "SIZE 5 EQUAL"], +["-549755813887", "SIZE 5 EQUAL"], +["-549755813888", "SIZE 6 EQUAL"], +["-9223372036854775807", "SIZE 8 EQUAL"], ["'abcdefghijklmnopqrstuvwxyz'", "SIZE 26 EQUAL"], @@ -306,6 +312,9 @@ ["8388608", "0x04 0x00008000 EQUAL"], ["2147483647", "0x04 0xFFFFFF7F EQUAL"], ["2147483648", "0x05 0x0000008000 EQUAL"], +["549755813887", "0x05 0xFFFFFFFF7F EQUAL"], +["549755813888", "0x06 0xFFFFFFFF7F EQUAL"], +["9223372036854775807", "0x08 0xFFFFFFFFFFFFFF7F EQUAL"], ["-1", "0x01 0x81 EQUAL", "Numbers are little-endian with the MSB being a sign bit"], ["-127", "0x01 0xFF EQUAL"], ["-128", "0x02 0x8080 EQUAL"], @@ -315,6 +324,10 @@ ["-8388608", "0x04 0x00008080 EQUAL"], ["-2147483647", "0x04 0xFFFFFFFF EQUAL"], ["-2147483648", "0x05 0x0000008080 EQUAL"], +["-4294967295", "0x05 0xFFFFFFFF80 EQUAL"], +["-549755813887", "0x05 0xFFFFFFFFFF EQUAL"], +["-549755813888", "0x06 0x000000008080 EQUAL"], +["-9223372036854775807", "0x08 0xFFFFFFFFFFFFFFFF EQUAL"], ["2147483647", "1ADD 2147483648 EQUAL", "We can do math on 4-byte integers, and compare 5-byte ones"], ["2147483647", "1ADD 1"], From 03dd134305b49b2f117b2d66d8229980715087fe Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Wed, 9 Apr 2014 19:30:59 +0100 Subject: [PATCH 125/174] adapt for btcec changes. --- opcode.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/opcode.go b/opcode.go index cfe78a70..998fc953 100644 --- a/opcode.go +++ b/opcode.go @@ -1806,7 +1806,7 @@ func opcodeCheckSig(op *parsedOpcode, s *Script) error { spew.Sdump(pkStr), pubKey.X, pubKey.Y, signature.R, signature.S, spew.Sdump(hash)) })) - ok := ecdsa.Verify(pubKey, hash, signature.R, signature.S) + ok := ecdsa.Verify(pubKey.ToECDSA(), hash, signature.R, signature.S) s.dstack.PushBool(ok) return nil } @@ -1845,7 +1845,7 @@ func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error { return StackErrTooManyOperations } pubKeyStrings := make([][]byte, npk) - pubKeys := make([]*ecdsa.PublicKey, npk) + pubKeys := make([]*btcec.PublicKey, npk) for i := range pubKeys { pubKeyStrings[i], err = s.dstack.PopByteArray() if err != nil { @@ -1930,7 +1930,7 @@ func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error { continue } } - success = ecdsa.Verify(pubKeys[curPk], hash, + success = ecdsa.Verify(pubKeys[curPk].ToECDSA(), hash, signatures[i].s.R, signatures[i].s.S) if success { break inner From 1240483592b478486af97afe94868b7770e21602 Mon Sep 17 00:00:00 2001 From: David Hill Date: Fri, 11 Apr 2014 14:54:44 -0400 Subject: [PATCH 126/174] gofmt --- script_test.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/script_test.go b/script_test.go index 5a65b184..2ded2dbd 100644 --- a/script_test.go +++ b/script_test.go @@ -1945,18 +1945,18 @@ var removeOpcodeByDataTests = []removeOpcodeByDataTest{ { // padded to keep it canonical. name: "simple case (pushdata1)", - before: append(append([]byte{btcscript.OP_PUSHDATA1, 76,}, - bytes.Repeat([]byte{0}, 72)...), []byte{1,2,3,4}...), + before: append(append([]byte{btcscript.OP_PUSHDATA1, 76}, + bytes.Repeat([]byte{0}, 72)...), []byte{1, 2, 3, 4}...), remove: []byte{1, 2, 3, 4}, after: []byte{}, }, { name: "simple case (pushdata1 miss)", - before: append(append([]byte{btcscript.OP_PUSHDATA1, 76,}, - bytes.Repeat([]byte{0}, 72)...), []byte{1,2,3,4}...), + before: append(append([]byte{btcscript.OP_PUSHDATA1, 76}, + bytes.Repeat([]byte{0}, 72)...), []byte{1, 2, 3, 4}...), remove: []byte{1, 2, 3, 5}, - after: append(append([]byte{btcscript.OP_PUSHDATA1, 76,}, - bytes.Repeat([]byte{0}, 72)...), []byte{1,2,3,4}...), + after: append(append([]byte{btcscript.OP_PUSHDATA1, 76}, + bytes.Repeat([]byte{0}, 72)...), []byte{1, 2, 3, 4}...), }, { name: "simple case (pushdata1 miss noncanonical)", @@ -1967,17 +1967,17 @@ var removeOpcodeByDataTests = []removeOpcodeByDataTest{ { name: "simple case (pushdata2)", before: append(append([]byte{btcscript.OP_PUSHDATA2, 0, 1}, - bytes.Repeat([]byte{0}, 252)...), []byte{1,2,3,4}...), + bytes.Repeat([]byte{0}, 252)...), []byte{1, 2, 3, 4}...), remove: []byte{1, 2, 3, 4}, after: []byte{}, }, { name: "simple case (pushdata2 miss)", before: append(append([]byte{btcscript.OP_PUSHDATA2, 0, 1}, - bytes.Repeat([]byte{0}, 252)...), []byte{1,2,3,4}...), + bytes.Repeat([]byte{0}, 252)...), []byte{1, 2, 3, 4}...), remove: []byte{1, 2, 3, 4, 5}, after: append(append([]byte{btcscript.OP_PUSHDATA2, 0, 1}, - bytes.Repeat([]byte{0}, 252)...), []byte{1,2,3,4}...), + bytes.Repeat([]byte{0}, 252)...), []byte{1, 2, 3, 4}...), }, { name: "simple case (pushdata2 miss noncanonical)", @@ -1989,7 +1989,7 @@ var removeOpcodeByDataTests = []removeOpcodeByDataTest{ // This is padded to make the push canonical. name: "simple case (pushdata4)", before: append(append([]byte{btcscript.OP_PUSHDATA4, 0, 0, 1, 0}, - bytes.Repeat([]byte{0}, 65532)...), []byte{1,2,3,4}...), + bytes.Repeat([]byte{0}, 65532)...), []byte{1, 2, 3, 4}...), remove: []byte{1, 2, 3, 4}, after: []byte{}, }, @@ -2003,10 +2003,10 @@ var removeOpcodeByDataTests = []removeOpcodeByDataTest{ // This is padded to make the push canonical. name: "simple case (pushdata4 miss)", before: append(append([]byte{btcscript.OP_PUSHDATA4, 0, 0, 1, 0}, - bytes.Repeat([]byte{0}, 65532)...), []byte{1,2,3,4}...), + bytes.Repeat([]byte{0}, 65532)...), []byte{1, 2, 3, 4}...), remove: []byte{1, 2, 3, 4, 5}, after: append(append([]byte{btcscript.OP_PUSHDATA4, 0, 0, 1, 0}, - bytes.Repeat([]byte{0}, 65532)...), []byte{1,2,3,4}...), + bytes.Repeat([]byte{0}, 65532)...), []byte{1, 2, 3, 4}...), }, { name: "invalid opcode ", From 76e8fa9766e30370cb242f89b944e131d8e40e56 Mon Sep 17 00:00:00 2001 From: David Hill Date: Thu, 1 May 2014 09:41:29 -0400 Subject: [PATCH 127/174] Reduce OP_RETURN standard relay bytes to 40. This matches commit 8175c790eb12f0b0ca3197895a6d1d479b340b67 of the reference software. --- script.go | 4 +- script_test.go | 14 +--- test_coverage.txt | 204 +++++++++++++++++++++++----------------------- 3 files changed, 108 insertions(+), 114 deletions(-) diff --git a/script.go b/script.go index 5f469685..e9e471d6 100644 --- a/script.go +++ b/script.go @@ -290,7 +290,7 @@ func isMultiSig(pops []parsedOpcode) bool { // false otherwise. func isNullData(pops []parsedOpcode) bool { // A nulldata transaction is either a single OP_RETURN or an - // OP_RETURN SMALLDATA (where SMALLDATA is a push data up to 80 bytes). + // OP_RETURN SMALLDATA (where SMALLDATA is a push data up to 40 bytes). l := len(pops) if l == 1 && pops[0].opcode.value == OP_RETURN { return true @@ -299,7 +299,7 @@ func isNullData(pops []parsedOpcode) bool { return l == 2 && pops[0].opcode.value == OP_RETURN && pops[1].opcode.value <= OP_PUSHDATA4 && - len(pops[1].data) <= 80 + len(pops[1].data) <= 40 } // isPushOnly returns true if the script only pushes data, false otherwise. diff --git a/script_test.go b/script_test.go index 2ded2dbd..abebc26b 100644 --- a/script_test.go +++ b/script_test.go @@ -2149,17 +2149,12 @@ var scriptTypeTests = []scriptTypeTest{ script: []byte{ btcscript.OP_RETURN, btcscript.OP_PUSHDATA1, - 0x50, + 0x28, // 40 0x04, 0x67, 0x08, 0xaf, 0xdb, 0x0f, 0xe5, 0x54, 0x82, 0x71, 0x96, 0x7f, 0x1a, 0x67, 0x13, 0x0b, 0x71, 0x05, 0xcd, 0x6a, 0x82, 0x8e, 0x03, 0x90, 0x9a, 0x67, 0x96, 0x2e, 0x0e, 0xa1, 0xf6, 0x1d, 0xeb, 0x64, 0x9f, 0x6b, 0xc3, 0xf4, 0xce, 0xf3, - 0x80, 0x46, 0x78, 0xaf, 0xdb, 0x0f, 0xe5, 0x54, - 0x82, 0x71, 0x96, 0x7f, 0x1a, 0x67, 0x13, 0x0b, - 0x71, 0x05, 0xcd, 0x6a, 0x82, 0x8e, 0x03, 0x90, - 0x9a, 0x67, 0x96, 0x2e, 0x0e, 0xa1, 0xf6, 0x1d, - 0xeb, 0x64, 0x9f, 0x6b, 0xc3, 0xf4, 0xce, 0xf3, }, scripttype: btcscript.NullDataTy, }, @@ -2169,17 +2164,12 @@ var scriptTypeTests = []scriptTypeTest{ script: []byte{ btcscript.OP_RETURN, btcscript.OP_PUSHDATA1, - 0x51, + 0x29, // 41 0x04, 0x67, 0x08, 0xaf, 0xdb, 0x0f, 0xe5, 0x54, 0x82, 0x71, 0x96, 0x7f, 0x1a, 0x67, 0x13, 0x0b, 0x71, 0x05, 0xcd, 0x6a, 0x82, 0x8e, 0x03, 0x90, 0x9a, 0x67, 0x96, 0x2e, 0x0e, 0xa1, 0xf6, 0x1d, 0xeb, 0x64, 0x9f, 0x6b, 0xc3, 0xf4, 0xce, 0xf3, - 0x80, 0x46, 0x78, 0xaf, 0xdb, 0x0f, 0xe5, 0x54, - 0x82, 0x71, 0x96, 0x7f, 0x1a, 0x67, 0x13, 0x0b, - 0x71, 0x05, 0xcd, 0x6a, 0x82, 0x8e, 0x03, 0x90, - 0x9a, 0x67, 0x96, 0x2e, 0x0e, 0xa1, 0xf6, 0x1d, - 0xeb, 0x64, 0x9f, 0x6b, 0xc3, 0xf4, 0xce, 0xf3, 0x08, }, scripttype: btcscript.NonStandardTy, diff --git a/test_coverage.txt b/test_coverage.txt index d98c67a6..51ea818b 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -1,167 +1,171 @@ github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 100.00% (60/60) -github.com/conformal/btcscript/script.go Script.Step 100.00% (36/36) +github.com/conformal/btcscript/script.go Script.Step 100.00% (37/37) +github.com/conformal/btcscript/opcode.go opcodeCheckSig 100.00% (29/29) github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (29/29) github.com/conformal/btcscript/address.go ExtractPkScriptAddrs 100.00% (27/27) github.com/conformal/btcscript/script.go CalcScriptInfo 100.00% (25/25) +github.com/conformal/btcscript/script.go NewScript 100.00% (23/23) github.com/conformal/btcscript/stack.go asInt 100.00% (23/23) github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23) -github.com/conformal/btcscript/script.go NewScript 100.00% (23/23) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddData 100.00% (19/19) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddData 100.00% (22/22) github.com/conformal/btcscript/opcode.go parsedOpcode.disabled 100.00% (17/17) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (16/16) +github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (15/15) github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (15/15) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) -github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (14/14) -github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) +github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (13/13) github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) -github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (12/12) -github.com/conformal/btcscript/script.go PayToAddrScript 100.00% (11/11) +github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) +github.com/conformal/btcscript/script.go typeOfScript 100.00% (11/11) +github.com/conformal/btcscript/script.go PayToAddrScript 100.00% (11/11) +github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) -github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) -github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) +github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/script.go Script.CheckErrorCondition 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) +github.com/conformal/btcscript/script.go Script.Execute 100.00% (8/8) github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) github.com/conformal/btcscript/script.go MultiSigScript 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) -github.com/conformal/btcscript/script.go typeOfScript 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) -github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddInt64 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddUint64 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) +github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodePick 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) -github.com/conformal/btcscript/opcode.go parsedOpcode.alwaysIllegal 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodePick 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) -github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) -github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) github.com/conformal/btcscript/script.go isNullData 100.00% (4/4) github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) -github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) -github.com/conformal/btcscript/script.go setStack 100.00% (3/3) -github.com/conformal/btcscript/script.go isSmallInt 100.00% (3/3) -github.com/conformal/btcscript/script.go asSmallInt 100.00% (3/3) +github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) +github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) +github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) +github.com/conformal/btcscript/opcode.go parsedOpcode.alwaysIllegal 100.00% (4/4) +github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) github.com/conformal/btcscript/script.go ScriptClass.String 100.00% (3/3) github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) -github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddOp 100.00% (2/2) +github.com/conformal/btcscript/script.go asSmallInt 100.00% (3/3) +github.com/conformal/btcscript/script.go setStack 100.00% (3/3) +github.com/conformal/btcscript/script.go isSmallInt 100.00% (3/3) github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Reset 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddOp 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) -github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Reset 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) +github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) -github.com/conformal/btcscript/log.go init 100.00% (1/1) -github.com/conformal/btcscript/scriptbuilder.go NewScriptBuilder 100.00% (1/1) -github.com/conformal/btcscript/opcode.go init 100.00% (1/1) -github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/script.go payToPubKeyHashScript 100.00% (1/1) -github.com/conformal/btcscript/script.go payToScriptHashScript 100.00% (1/1) -github.com/conformal/btcscript/script.go payToPubKeyScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) -github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) -github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) +github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) +github.com/conformal/btcscript/log.go init 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) +github.com/conformal/btcscript/script.go payToPubKeyHashScript 100.00% (1/1) +github.com/conformal/btcscript/script.go payToScriptHashScript 100.00% (1/1) +github.com/conformal/btcscript/script.go payToPubKeyScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) +github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) +github.com/conformal/btcscript/scriptbuilder.go NewScriptBuilder 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/opcode.go init 100.00% (1/1) +github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) github.com/conformal/btcscript/script.go calcScriptHash 97.44% (38/39) -github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.67% (29/30) github.com/conformal/btcscript/script.go canonicalPush 92.86% (13/14) github.com/conformal/btcscript/script.go unparseScript 85.71% (6/7) github.com/conformal/btcscript/script.go expectedInputs 85.71% (6/7) -github.com/conformal/btcscript/script.go Script.CheckErrorCondition 75.00% (9/12) github.com/conformal/btcscript/script.go IsPushOnlyScript 75.00% (3/4) github.com/conformal/btcscript/script.go HasCanonicalPushes 71.43% (5/7) -github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/10) github.com/conformal/btcscript/script.go CalcMultiSigStats 0.00% (0/8) +github.com/conformal/btcscript/script.go @577:34 0.00% (0/6) +github.com/conformal/btcscript/script.go @565:34 0.00% (0/4) +github.com/conformal/btcscript/script.go @610:34 0.00% (0/3) github.com/conformal/btcscript/log.go UseLogger 0.00% (0/1) -github.com/conformal/btcscript/opcode.go opcodeDisabled 0.00% (0/1) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript --------------------------- 96.20% (1063/1105) +github.com/conformal/btcscript/opcode.go @1803:33 0.00% (0/1) +github.com/conformal/btcscript/opcode.go opcodeDisabled 0.00% (0/1) +github.com/conformal/btcscript --------------------------- 96.23% (1073/1115) From 6e2ba386dd36cd3f17be86d898337f4db82ce6ef Mon Sep 17 00:00:00 2001 From: "Owain G. Ainsworth" Date: Thu, 17 Apr 2014 23:15:30 +0100 Subject: [PATCH 128/174] Add an entypoint to sign and verify a transaction input. This handles merging in of previous scripts, also. Add tests for the important paths. ok @davecgh --- internal_test.go | 12 - script.go | 398 ++++++++++++- script_test.go | 1421 ++++++++++++++++++++++++++++++++++++++++++++- test_coverage.txt | 216 +++---- 4 files changed, 1885 insertions(+), 162 deletions(-) diff --git a/internal_test.go b/internal_test.go index ba299f0d..7b86d1be 100644 --- a/internal_test.go +++ b/internal_test.go @@ -5,14 +5,12 @@ package btcscript import ( - "crypto/ecdsa" "encoding/hex" "encoding/json" "errors" "fmt" "github.com/conformal/btcutil" "github.com/conformal/btcwire" - "io" "io/ioutil" "strconv" "strings" @@ -47,16 +45,6 @@ func (s *Script) TstSetPC(script, off int) { s.scriptoff = off } -// TstSignatureScriptCustomReader allows the test modules to test the internal -// function signatureScriptCustomReader. -func TstSignatureScriptCustomReader(reader io.Reader, tx *btcwire.MsgTx, idx int, - subscript []byte, hashType byte, privkey *ecdsa.PrivateKey, - compress bool) ([]byte, error) { - - return signatureScriptCustomReader(reader, tx, idx, subscript, - hashType, privkey, compress) -} - // Internal tests for opcodde parsing with bad data templates. func TestParseOpcode(t *testing.T) { fakemap := make(map[byte]*opcode) diff --git a/script.go b/script.go index e9e471d6..21e91089 100644 --- a/script.go +++ b/script.go @@ -1089,27 +1089,10 @@ func MultiSigScript(pubkeys []*btcutil.AddressPubKey, nrequired int) ([]byte, er // compress. This format must match the same format used to generate // the payment address, or the script validation will fail. func SignatureScript(tx *btcwire.MsgTx, idx int, subscript []byte, hashType byte, privkey *ecdsa.PrivateKey, compress bool) ([]byte, error) { - return signatureScriptCustomReader(rand.Reader, tx, idx, subscript, - hashType, privkey, compress) -} - -// This function exists so we can test ecdsa.Sign's error for an invalid -// reader. -func signatureScriptCustomReader(reader io.Reader, tx *btcwire.MsgTx, idx int, - subscript []byte, hashType byte, privkey *ecdsa.PrivateKey, - compress bool) ([]byte, error) { - - parsedScript, err := parseScript(subscript) + sig, err := signTxOutput(tx, idx, subscript, hashType, privkey) if err != nil { - return nil, fmt.Errorf("cannot parse output script: %v", err) + return nil, err } - hash := calcScriptHash(parsedScript, hashType, tx, idx) - r, s, err := ecdsa.Sign(reader, privkey, hash) - if err != nil { - return nil, fmt.Errorf("cannot sign tx input: %s", err) - } - ecSig := btcec.Signature{R: r, S: s} - sig := append(ecSig.Serialize(), hashType) pk := (*btcec.PublicKey)(&privkey.PublicKey) var pkData []byte @@ -1122,6 +1105,383 @@ func signatureScriptCustomReader(reader io.Reader, tx *btcwire.MsgTx, idx int, return NewScriptBuilder().AddData(sig).AddData(pkData).Script(), nil } +func signTxOutput(tx *btcwire.MsgTx, idx int, subScript []byte, hashType byte, + key *ecdsa.PrivateKey) ([]byte, error) { + + return signTxOutputCustomReader(rand.Reader, tx, idx, subScript, + hashType, key) +} + +func signTxOutputCustomReader(reader io.Reader, tx *btcwire.MsgTx, idx int, + subScript []byte, hashType byte, key *ecdsa.PrivateKey) ([]byte, error) { + parsedScript, err := parseScript(subScript) + if err != nil { + return nil, fmt.Errorf("cannot parse output script: %v", err) + } + hash := calcScriptHash(parsedScript, hashType, tx, idx) + r, s, err := ecdsa.Sign(reader, key, hash) + if err != nil { + return nil, fmt.Errorf("cannot sign tx input: %s", err) + } + + return append((&btcec.Signature{R: r, S: s}).Serialize(), hashType), nil +} + +func p2pkSignatureScript(tx *btcwire.MsgTx, idx int, subScript []byte, hashType byte, privkey *ecdsa.PrivateKey) ([]byte, error) { + sig, err := signTxOutput(tx, idx, subScript, hashType, privkey) + if err != nil { + return nil, err + } + + return NewScriptBuilder().AddData(sig).Script(), nil +} + +// signMultiSig signs as many of the outputs in the provided multisig script as +// possible. It returns the generated script and a boolean if the script fulfils +// the contract (i.e. nrequired signatures are provided). Since it is arguably +// legal to not be able to sign any of the outputs, no error is returned. +func signMultiSig(tx *btcwire.MsgTx, idx int, subScript []byte, hashType byte, + addresses []btcutil.Address, nRequired int, kdb KeyDB) ([]byte, bool) { + // We start with a single OP_FALSE to work around the (now standard) + // but in the reference implementation that causes a spurious pop at + // the end of OP_CHECKMULTISIG. + builder := NewScriptBuilder().AddOp(OP_FALSE) + signed := 0 + for _, addr := range addresses { + key, _, err := kdb.GetKey(addr) + if err != nil { + continue + } + sig, err := signTxOutput(tx, idx, subScript, hashType, key) + if err != nil { + continue + } + + builder.AddData(sig) + signed++ + if signed == nRequired { + break + } + + } + + return builder.Script(), signed == nRequired +} + +func sign(net btcwire.BitcoinNet, tx *btcwire.MsgTx, idx int, subScript []byte, + hashType byte, kdb KeyDB, sdb ScriptDB) ([]byte, ScriptClass, + []btcutil.Address, int, error) { + + class, addresses, nrequired, err := ExtractPkScriptAddrs(subScript, net) + if err != nil { + return nil, NonStandardTy, nil, 0, err + } + + switch class { + case PubKeyTy: + // look up key for address + key, _, err := kdb.GetKey(addresses[0]) + if err != nil { + return nil, class, nil, 0, err + } + + script, err := p2pkSignatureScript(tx, idx, subScript, hashType, + key) + if err != nil { + return nil, class, nil, 0, err + } + + return script, class, addresses, nrequired, nil + case PubKeyHashTy: + // look up key for address + key, compressed, err := kdb.GetKey(addresses[0]) + if err != nil { + return nil, class, nil, 0, err + } + + script, err := SignatureScript(tx, idx, subScript, hashType, + key, compressed) + if err != nil { + return nil, class, nil, 0, err + } + + return script, class, addresses, nrequired, nil + case ScriptHashTy: + script, err := sdb.GetScript(addresses[0]) + if err != nil { + return nil, class, nil, 0, err + } + + return script, class, addresses, nrequired, nil + case MultiSigTy: + script, _ := signMultiSig(tx, idx, subScript, hashType, + addresses, nrequired, kdb) + return script, class, addresses, nrequired, nil + case NullDataTy: + return nil, class, nil, 0, + errors.New("can't sign NULLDATA transactions") + default: + return nil, class, nil, 0, + errors.New("can't sign unknown transactions") + } +} + +// mergeScripts merges sigScript and prevScript assuming they are both +// partial solutions for pkScript spending output idx of tx. class, addresses +// and nrequired are the result of extracting the addresses from pkscript. +// The return value is the best effort merging of the two scripts. Calling this +// function with addresses, class and nrequired that do not match pkScript is +// an error and results in undefined behaviour. +func mergeScripts(net btcwire.BitcoinNet, tx *btcwire.MsgTx, idx int, + pkScript []byte, class ScriptClass, addresses []btcutil.Address, + nRequired int, sigScript, prevScript []byte) []byte { + + // TODO(oga) the scripthash and multisig paths here are overly + // inefficient in that they will recompute already known data. + // some internal refactoring could probably make this avoid needless + // extra calculations. + switch class { + case ScriptHashTy: + // Remove the last push in the script and then recurse. + // this could be a lot less inefficient. + sigPops, err := parseScript(sigScript) + if err != nil || len(sigPops) == 0 { + return prevScript + } + prevPops, err := parseScript(prevScript) + if err != nil || len(prevPops) == 0 { + return sigScript + } + + // assume that script in sigPops is the correct one, we just + // made it. + script := sigPops[len(sigPops)-1].data + + // We already know this information somewhere up the stack. + class, addresses, nrequired, err := + ExtractPkScriptAddrs(script, net) + + // regenerate scripts. + sigScript, _ := unparseScript(sigPops) + prevScript, _ := unparseScript(prevPops) + + // Merge + mergedScript := mergeScripts(net, tx, idx, script, class, + addresses, nrequired, sigScript, prevScript) + + // Reappend the script and return the result. + builder := NewScriptBuilder() + builder.script = mergedScript + builder.AddData(script) + return builder.Script() + case MultiSigTy: + return mergeMultiSig(tx, idx, addresses, nRequired, pkScript, + sigScript, prevScript) + + // It doesn't actualy make sense to merge anything other than multiig + // and scripthash (because it could contain multisig). Everything else + // has either zero signature, can't be spent, or has a single signature + // which is either present or not. The other two cases are handled + // above. In the conflict case here we just assume the longest is + // correct (this matches behaviour of the reference implementation). + default: + if len(sigScript) > len(prevScript) { + return sigScript + } + return prevScript + } +} + +// mergeMultiSig combines the two signature scripts sigScript and prevScript +// that both provide signatures for pkScript in output idx of tx. addresses +// and nRequired should be the results from extracting the addresses from +// pkScript. Since this function is internal only we assume that the arguments +// have come from other functions internally and thus are all consistent with +// each other, behaviour is undefined if this contract is broken. +func mergeMultiSig(tx *btcwire.MsgTx, idx int, addresses []btcutil.Address, + nRequired int, pkScript, sigScript, prevScript []byte) []byte { + + // This is an internal only function and we already parsed this script + // as ok for multisig (this is how we got here), so if this fails then + // all assumptions are broken and who knows which way is up? + pkPops, _ := parseScript(pkScript) + + sigPops, err := parseScript(sigScript) + if err != nil || len(sigPops) == 0 { + return prevScript + } + + prevPops, err := parseScript(prevScript) + if err != nil || len(prevPops) == 0 { + return sigScript + } + + // Convenience function to avoid duplication. + extractSigs := func(pops []parsedOpcode, sigs [][]byte) [][]byte { + for _, pop := range pops { + if len(pop.data) != 0 { + sigs = append(sigs, pop.data) + } + } + return sigs + } + + possibleSigs := make([][]byte, 0, len(sigPops)+len(prevPops)) + possibleSigs = extractSigs(sigPops, possibleSigs) + possibleSigs = extractSigs(prevPops, possibleSigs) + + // Now we need to match the signatures to pubkeys, the only real way to + // do that is to try to verify them all and match it to the pubkey + // that verifies it. we then can go through the addresses in order + // to build our script. Anything that doesn't parse or doesn't verify we + // throw away. + addrToSig := make(map[string][]byte) +sigLoop: + for _, sig := range possibleSigs { + + // can't have a valid signature that doesn't at least have a + // hashtype, in practise it is even longer than this. but + // that'll be checked next. + if len(sig) < 1 { + continue + } + tSig := sig[:len(sig)-1] + hashType := sig[len(sig)-1] + + pSig, err := btcec.ParseDERSignature(tSig, btcec.S256()) + if err != nil { + continue + } + + // We have to do this each round since hash types may vary + // between signatures and so the hash will vary. We can, + // however, assume no sigs etc are in the script since that + // would make the transaction nonstandard and thus not + // MultiSigTy, so we just need to hash the full thing. + hash := calcScriptHash(pkPops, hashType, tx, idx) + + for _, addr := range addresses { + // All multisig addresses should be pubkey addreses + // it is an error to call this internal function with + // bad input. + pkaddr := addr.(*btcutil.AddressPubKey) + + pubKey := pkaddr.PubKey() + + // If it matches we put it in the map. We only + // can take one signature per public key so if we + // already have one, we can throw this away. + if ecdsa.Verify(pubKey.ToECDSA(), hash, + pSig.R, pSig.S) { + + aStr := addr.EncodeAddress() + if _, ok := addrToSig[aStr]; !ok { + addrToSig[aStr] = sig + } + continue sigLoop + } + } + } + + // Extra opcode to handle the extra arg consumed (due to previous bugs + // in the reference implementation). + builder := NewScriptBuilder().AddOp(OP_FALSE) + doneSigs := 0 + // This assumes that addresses are in the same order as in the script. + for _, addr := range addresses { + sig, ok := addrToSig[addr.EncodeAddress()] + if !ok { + continue + } + builder.AddData(sig) + doneSigs++ + if doneSigs == nRequired { + break + } + } + + // padding for missing ones. + for i := doneSigs; i < nRequired; i++ { + builder.AddOp(OP_0) + } + + return builder.Script() +} + +// KeyDB is an interface type provided to SignTxOutput, it encapsulates +// any user state required to get the private keys for an address. +type KeyDB interface { + GetKey(btcutil.Address) (*ecdsa.PrivateKey, bool, error) +} + +// KeyClosure implements ScriptDB with a closure +type KeyClosure func(btcutil.Address) (*ecdsa.PrivateKey, bool, error) + +// GetKey implements KeyDB by returning the result of calling the closure +func (kc KeyClosure) GetKey(address btcutil.Address) (*ecdsa.PrivateKey, + bool, error) { + return kc(address) +} + +// ScriptDB is an interface type provided to SignTxOutput, it encapsulates +// any user state required to get the scripts for an pay-to-script-hash address. +type ScriptDB interface { + GetScript(btcutil.Address) ([]byte, error) +} + +// ScriptClosure implements ScriptDB with a closure +type ScriptClosure func(btcutil.Address) ([]byte, error) + +// GetScript implements ScriptDB by returning the result of calling the closure +func (sc ScriptClosure) GetScript(address btcutil.Address) ([]byte, error) { + return sc(address) +} + +// SignTxOutput signs output idx of the given tx to resolve the script given in +// pkScript with a signature type of hashType. Any keys required will be +// looked up by calling getKey() with the string of the given address. +// Any pay-to-script-hash signatures will be similarly lookedu p by calling +// getScript. If previousScript is provided then the results in previousScript +// will be merged in a type-dependant manner with the newly generated. +// signature script. +func SignTxOutput(net btcwire.BitcoinNet, tx *btcwire.MsgTx, idx int, + pkScript []byte, hashType byte, kdb KeyDB, sdb ScriptDB, + previousScript []byte) ([]byte, error) { + + sigScript, class, addresses, nrequired, err := sign(net, tx, idx, + pkScript, hashType, kdb, sdb) + if err != nil { + return nil, err + } + + if class == ScriptHashTy { + // TODO keep the sub addressed and pass down to merge. + realSigScript, _, _, _, err := sign(net, tx, idx, sigScript, + hashType, kdb, sdb) + if err != nil { + return nil, err + } + + // This is a bad thing. Append the p2sh script as the last + // push in the script. + builder := NewScriptBuilder() + builder.script = realSigScript + builder.AddData(sigScript) + + sigScript = builder.Script() + // TODO keep a copy of the script for merging. + } + + // Merge scripts. with any previous data, if any. + mergedScript := mergeScripts(net, tx, idx, pkScript, class, addresses, + nrequired, sigScript, previousScript) + if err != nil { + return nil, err + } + + return mergedScript, nil +} + // expectedInputs returns the number of arguments required by a script. // If the script is of unnown type such that the number can not be determined // then -1 is returned. We are an internal function and thus assume that class diff --git a/script_test.go b/script_test.go index abebc26b..54b98b3f 100644 --- a/script_test.go +++ b/script_test.go @@ -7,6 +7,9 @@ package btcscript_test import ( "bytes" "crypto/ecdsa" + "crypto/rand" + "errors" + "fmt" "github.com/conformal/btcec" "github.com/conformal/btcscript" "github.com/conformal/btcutil" @@ -2463,7 +2466,6 @@ type TstInput struct { sigscriptGenerates bool inputValidates bool indexOutOfRange bool - invalidReader bool } var coinbaseOutPoint = &btcwire.OutPoint{ @@ -2694,19 +2696,6 @@ var SigScriptTests = []TstSigScript{ compress: false, scriptAtWrongIndex: true, }, - { - name: "invalid reader", - inputs: []TstInput{ - { - txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), - invalidReader: true, - sigscriptGenerates: false, - }, - }, - hashtype: btcscript.SigHashAll, - compress: false, - scriptAtWrongIndex: true, - }, } // Test the sigscript generation for valid and invalid inputs, all @@ -2749,20 +2738,10 @@ nexttest: } else { idx = j } - if SigScriptTests[i].inputs[j].invalidReader { - script, err = btcscript.TstSignatureScriptCustomReader( - new(bytes.Buffer), tx, idx, - SigScriptTests[i].inputs[j].txout.PkScript, - SigScriptTests[i].hashtype, - privkey, - SigScriptTests[i].compress) - } else { - script, err = btcscript.SignatureScript(tx, idx, - SigScriptTests[i].inputs[j].txout.PkScript, - SigScriptTests[i].hashtype, - privkey, - SigScriptTests[i].compress) - } + script, err = btcscript.SignatureScript(tx, idx, + SigScriptTests[i].inputs[j].txout.PkScript, + SigScriptTests[i].hashtype, privkey, + SigScriptTests[i].compress) if (err == nil) != SigScriptTests[i].inputs[j].sigscriptGenerates { if err == nil { @@ -3190,3 +3169,1389 @@ func TestMultiSigScript(t *testing.T) { } } } + +func signAndCheck(msg string, tx *btcwire.MsgTx, idx int, pkScript []byte, + hashType byte, kdb btcscript.KeyDB, sdb btcscript.ScriptDB, + previousScript []byte) error { + + sigScript, err := btcscript.SignTxOutput( + btcwire.TestNet3, tx, idx, pkScript, hashType, + kdb, sdb, []byte{}) + if err != nil { + return fmt.Errorf("failed to sign output %s: %v", msg, err) + } + + return checkScripts(msg, tx, idx, sigScript, pkScript) +} + +func checkScripts(msg string, tx *btcwire.MsgTx, idx int, + sigScript, pkScript []byte) error { + engine, err := btcscript.NewScript(sigScript, pkScript, idx, tx, + btcscript.ScriptBip16| + btcscript.ScriptCanonicalSignatures) + if err != nil { + return fmt.Errorf("failed to make script engine for %s: %v", + msg, err) + } + + err = engine.Execute() + if err != nil { + return fmt.Errorf("invalid script signature for %s: %v", msg, + err) + } + + return nil +} + +type addressToKey struct { + key *ecdsa.PrivateKey + compressed bool +} + +func mkGetKey(keys map[string]addressToKey) btcscript.KeyDB { + if keys == nil { + return btcscript.KeyClosure(func(addr btcutil.Address) (*ecdsa.PrivateKey, + bool, error) { + return nil, false, errors.New("nope") + }) + } + return btcscript.KeyClosure(func(addr btcutil.Address) (*ecdsa.PrivateKey, + bool, error) { + a2k, ok := keys[addr.EncodeAddress()] + if !ok { + return nil, false, errors.New("nope") + } + return a2k.key, a2k.compressed, nil + }) +} + +func mkGetScript(scripts map[string][]byte) btcscript.ScriptDB { + if scripts == nil { + return btcscript.ScriptClosure(func(addr btcutil.Address) ( + []byte, error) { + return nil, errors.New("nope") + }) + } + return btcscript.ScriptClosure(func(addr btcutil.Address) ([]byte, + error) { + script, ok := scripts[addr.EncodeAddress()] + if !ok { + return nil, errors.New("nope") + } + return script, nil + }) +} + +func TestSignTxOutput(t *testing.T) { + // make key + // make script based on key. + // sign with magic pixie dust. + hashTypes := []byte{ + btcscript.SigHashOld, // no longer used but should act like all + btcscript.SigHashAll, + btcscript.SigHashNone, + btcscript.SigHashSingle, + btcscript.SigHashAll | btcscript.SigHashAnyOneCanPay, + btcscript.SigHashNone | btcscript.SigHashAnyOneCanPay, + btcscript.SigHashSingle | btcscript.SigHashAnyOneCanPay, + } + tx := &btcwire.MsgTx{ + Version: 1, + TxIn: []*btcwire.TxIn{ + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash{}, + Index: 0, + }, + Sequence: 4294967295, + }, + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash{}, + Index: 1, + }, + Sequence: 4294967295, + }, + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash{}, + Index: 2, + }, + Sequence: 4294967295, + }, + }, + TxOut: []*btcwire.TxOut{ + &btcwire.TxOut{ + Value: 1, + }, + &btcwire.TxOut{ + Value: 2, + }, + &btcwire.TxOut{ + Value: 3, + }, + }, + LockTime: 0, + } + + // Pay to Pubkey Hash (uncompressed) + for _, hashType := range hashTypes { + for i := range tx.TxIn { + msg := fmt.Sprintf("%d:%d", hashType, i) + key, err := ecdsa.GenerateKey(btcec.S256(), + rand.Reader) + if err != nil { + t.Errorf("failed to make privkey for %s: %v", + msg, err) + break + } + + pk := (*btcec.PublicKey)(&key.PublicKey). + SerializeUncompressed() + address, err := btcutil.NewAddressPubKeyHash( + btcutil.Hash160(pk), btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make address for %s: %v", + msg, err) + break + } + + pkScript, err := btcscript.PayToAddrScript(address) + if err != nil { + t.Errorf("failed to make pkscript "+ + "for %s: %v", msg, err) + } + + if err := signAndCheck(msg, tx, i, pkScript, hashType, + mkGetKey(map[string]addressToKey{ + address.EncodeAddress(): {key, false}, + }), mkGetScript(nil), []byte{}); err != nil { + t.Error(err) + break + } + } + } + + // Pay to Pubkey Hash (uncompressed) (merging with correct) + for _, hashType := range hashTypes { + for i := range tx.TxIn { + msg := fmt.Sprintf("%d:%d", hashType, i) + key, err := ecdsa.GenerateKey(btcec.S256(), + rand.Reader) + if err != nil { + t.Errorf("failed to make privkey for %s: %v", + msg, err) + break + } + + pk := (*btcec.PublicKey)(&key.PublicKey). + SerializeUncompressed() + address, err := btcutil.NewAddressPubKeyHash( + btcutil.Hash160(pk), btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make address for %s: %v", + msg, err) + break + } + + pkScript, err := btcscript.PayToAddrScript(address) + if err != nil { + t.Errorf("failed to make pkscript "+ + "for %s: %v", msg, err) + } + + sigScript, err := btcscript.SignTxOutput( + btcwire.TestNet3, tx, i, pkScript, + hashType, mkGetKey(map[string]addressToKey{ + address.EncodeAddress(): {key, false}, + }), mkGetScript(nil), []byte{}) + if err != nil { + t.Errorf("failed to sign output %s: %v", msg, + err) + break + } + + // by the above loop, this should be valid, now sign + // again and merge. + sigScript, err = btcscript.SignTxOutput( + btcwire.TestNet3, tx, i, pkScript, + hashType, mkGetKey(map[string]addressToKey{ + address.EncodeAddress(): {key, false}, + }), mkGetScript(nil), sigScript) + if err != nil { + t.Errorf("failed to sign output %s a "+ + "second time: %v", msg, err) + break + } + + err = checkScripts(msg, tx, i, sigScript, pkScript) + if err != nil { + t.Errorf("twice signed script invalid for "+ + "%s: %v", msg, err) + break + } + } + } + + // Pay to Pubkey Hash (compressed) + for _, hashType := range hashTypes { + for i := range tx.TxIn { + msg := fmt.Sprintf("%d:%d", hashType, i) + + key, err := ecdsa.GenerateKey(btcec.S256(), + rand.Reader) + if err != nil { + t.Errorf("failed to make privkey for %s: %v", + msg, err) + break + } + + pk := (*btcec.PublicKey)(&key.PublicKey). + SerializeCompressed() + address, err := btcutil.NewAddressPubKeyHash( + btcutil.Hash160(pk), btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make address for %s: %v", + msg, err) + break + } + + pkScript, err := btcscript.PayToAddrScript(address) + if err != nil { + t.Errorf("failed to make pkscript "+ + "for %s: %v", msg, err) + } + + if err := signAndCheck(msg, tx, i, pkScript, hashType, + mkGetKey(map[string]addressToKey{ + address.EncodeAddress(): {key, true}, + }), mkGetScript(nil), []byte{}); err != nil { + t.Error(err) + break + } + } + } + + // Pay to Pubkey Hash (compressed) with duplicate merge + for _, hashType := range hashTypes { + for i := range tx.TxIn { + msg := fmt.Sprintf("%d:%d", hashType, i) + + key, err := ecdsa.GenerateKey(btcec.S256(), + rand.Reader) + if err != nil { + t.Errorf("failed to make privkey for %s: %v", + msg, err) + break + } + + pk := (*btcec.PublicKey)(&key.PublicKey). + SerializeCompressed() + address, err := btcutil.NewAddressPubKeyHash( + btcutil.Hash160(pk), btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make address for %s: %v", + msg, err) + break + } + + pkScript, err := btcscript.PayToAddrScript(address) + if err != nil { + t.Errorf("failed to make pkscript "+ + "for %s: %v", msg, err) + } + + sigScript, err := btcscript.SignTxOutput( + btcwire.TestNet3, tx, i, pkScript, + hashType, mkGetKey(map[string]addressToKey{ + address.EncodeAddress(): {key, true}, + }), mkGetScript(nil), []byte{}) + if err != nil { + t.Errorf("failed to sign output %s: %v", msg, + err) + break + } + + // by the above loop, this should be valid, now sign + // again and merge. + sigScript, err = btcscript.SignTxOutput( + btcwire.TestNet3, tx, i, pkScript, + hashType, mkGetKey(map[string]addressToKey{ + address.EncodeAddress(): {key, true}, + }), mkGetScript(nil), sigScript) + if err != nil { + t.Errorf("failed to sign output %s a "+ + "second time: %v", msg, err) + break + } + + err = checkScripts(msg, tx, i, sigScript, pkScript) + if err != nil { + t.Errorf("twice signed script invalid for "+ + "%s: %v", msg, err) + break + } + } + } + + // Pay to PubKey (uncompressed) + for _, hashType := range hashTypes { + for i := range tx.TxIn { + msg := fmt.Sprintf("%d:%d", hashType, i) + + key, err := ecdsa.GenerateKey(btcec.S256(), + rand.Reader) + if err != nil { + t.Errorf("failed to make privkey for %s: %v", + msg, err) + break + } + + pk := (*btcec.PublicKey)(&key.PublicKey). + SerializeUncompressed() + address, err := btcutil.NewAddressPubKey(pk, + btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make address for %s: %v", + msg, err) + break + } + + pkScript, err := btcscript.PayToAddrScript(address) + if err != nil { + t.Errorf("failed to make pkscript "+ + "for %s: %v", msg, err) + } + + if err := signAndCheck(msg, tx, i, pkScript, hashType, + mkGetKey(map[string]addressToKey{ + address.EncodeAddress(): {key, false}, + }), mkGetScript(nil), []byte{}); err != nil { + t.Error(err) + break + } + } + } + + // Pay to PubKey (uncompressed) + for _, hashType := range hashTypes { + for i := range tx.TxIn { + msg := fmt.Sprintf("%d:%d", hashType, i) + + key, err := ecdsa.GenerateKey(btcec.S256(), + rand.Reader) + if err != nil { + t.Errorf("failed to make privkey for %s: %v", + msg, err) + break + } + + pk := (*btcec.PublicKey)(&key.PublicKey). + SerializeUncompressed() + address, err := btcutil.NewAddressPubKey(pk, + btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make address for %s: %v", + msg, err) + break + } + + pkScript, err := btcscript.PayToAddrScript(address) + if err != nil { + t.Errorf("failed to make pkscript "+ + "for %s: %v", msg, err) + } + + sigScript, err := btcscript.SignTxOutput( + btcwire.TestNet3, tx, i, pkScript, + hashType, mkGetKey(map[string]addressToKey{ + address.EncodeAddress(): {key, false}, + }), mkGetScript(nil), []byte{}) + if err != nil { + t.Errorf("failed to sign output %s: %v", msg, + err) + break + } + + // by the above loop, this should be valid, now sign + // again and merge. + sigScript, err = btcscript.SignTxOutput( + btcwire.TestNet3, tx, i, pkScript, + hashType, mkGetKey(map[string]addressToKey{ + address.EncodeAddress(): {key, false}, + }), mkGetScript(nil), sigScript) + if err != nil { + t.Errorf("failed to sign output %s a "+ + "second time: %v", msg, err) + break + } + + err = checkScripts(msg, tx, i, sigScript, pkScript) + if err != nil { + t.Errorf("twice signed script invalid for "+ + "%s: %v", msg, err) + break + } + } + } + + // Pay to PubKey (compressed) + for _, hashType := range hashTypes { + for i := range tx.TxIn { + msg := fmt.Sprintf("%d:%d", hashType, i) + + key, err := ecdsa.GenerateKey(btcec.S256(), + rand.Reader) + if err != nil { + t.Errorf("failed to make privkey for %s: %v", + msg, err) + break + } + + pk := (*btcec.PublicKey)(&key.PublicKey). + SerializeCompressed() + address, err := btcutil.NewAddressPubKey(pk, + btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make address for %s: %v", + msg, err) + break + } + + pkScript, err := btcscript.PayToAddrScript(address) + if err != nil { + t.Errorf("failed to make pkscript "+ + "for %s: %v", msg, err) + } + + if err := signAndCheck(msg, tx, i, pkScript, hashType, + mkGetKey(map[string]addressToKey{ + address.EncodeAddress(): {key, true}, + }), mkGetScript(nil), []byte{}); err != nil { + t.Error(err) + break + } + } + } + + // Pay to PubKey (compressed) with duplicate merge + for _, hashType := range hashTypes { + for i := range tx.TxIn { + msg := fmt.Sprintf("%d:%d", hashType, i) + + key, err := ecdsa.GenerateKey(btcec.S256(), + rand.Reader) + if err != nil { + t.Errorf("failed to make privkey for %s: %v", + msg, err) + break + } + + pk := (*btcec.PublicKey)(&key.PublicKey). + SerializeCompressed() + address, err := btcutil.NewAddressPubKey(pk, + btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make address for %s: %v", + msg, err) + break + } + + pkScript, err := btcscript.PayToAddrScript(address) + if err != nil { + t.Errorf("failed to make pkscript "+ + "for %s: %v", msg, err) + } + + sigScript, err := btcscript.SignTxOutput( + btcwire.TestNet3, tx, i, pkScript, + hashType, mkGetKey(map[string]addressToKey{ + address.EncodeAddress(): {key, true}, + }), mkGetScript(nil), []byte{}) + if err != nil { + t.Errorf("failed to sign output %s: %v", msg, + err) + break + } + + // by the above loop, this should be valid, now sign + // again and merge. + sigScript, err = btcscript.SignTxOutput( + btcwire.TestNet3, tx, i, pkScript, + hashType, mkGetKey(map[string]addressToKey{ + address.EncodeAddress(): {key, true}, + }), mkGetScript(nil), sigScript) + if err != nil { + t.Errorf("failed to sign output %s a "+ + "second time: %v", msg, err) + break + } + + err = checkScripts(msg, tx, i, sigScript, pkScript) + if err != nil { + t.Errorf("twice signed script invalid for "+ + "%s: %v", msg, err) + break + } + } + } + + // As before, but with p2sh now. + // Pay to Pubkey Hash (uncompressed) + for _, hashType := range hashTypes { + for i := range tx.TxIn { + msg := fmt.Sprintf("%d:%d", hashType, i) + key, err := ecdsa.GenerateKey(btcec.S256(), + rand.Reader) + if err != nil { + t.Errorf("failed to make privkey for %s: %v", + msg, err) + break + } + + pk := (*btcec.PublicKey)(&key.PublicKey). + SerializeUncompressed() + address, err := btcutil.NewAddressPubKeyHash( + btcutil.Hash160(pk), btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make address for %s: %v", + msg, err) + break + } + + pkScript, err := btcscript.PayToAddrScript(address) + if err != nil { + t.Errorf("failed to make pkscript "+ + "for %s: %v", msg, err) + break + } + + scriptAddr, err := btcutil.NewAddressScriptHash( + pkScript, btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make p2sh addr for %s: %v", + msg, err) + break + } + + scriptPkScript, err := btcscript.PayToAddrScript( + scriptAddr) + if err != nil { + t.Errorf("failed to make script pkscript for "+ + "%s: %v", msg, err) + break + } + + if err := signAndCheck(msg, tx, i, scriptPkScript, + hashType, + mkGetKey(map[string]addressToKey{ + address.EncodeAddress(): {key, false}, + }), mkGetScript(map[string][]byte{ + scriptAddr.EncodeAddress(): pkScript, + }), []byte{}); err != nil { + t.Error(err) + break + } + } + } + + // Pay to Pubkey Hash (uncompressed) with duplicate merge + for _, hashType := range hashTypes { + for i := range tx.TxIn { + msg := fmt.Sprintf("%d:%d", hashType, i) + key, err := ecdsa.GenerateKey(btcec.S256(), + rand.Reader) + if err != nil { + t.Errorf("failed to make privkey for %s: %v", + msg, err) + break + } + + pk := (*btcec.PublicKey)(&key.PublicKey). + SerializeUncompressed() + address, err := btcutil.NewAddressPubKeyHash( + btcutil.Hash160(pk), btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make address for %s: %v", + msg, err) + break + } + + pkScript, err := btcscript.PayToAddrScript(address) + if err != nil { + t.Errorf("failed to make pkscript "+ + "for %s: %v", msg, err) + break + } + + scriptAddr, err := btcutil.NewAddressScriptHash( + pkScript, btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make p2sh addr for %s: %v", + msg, err) + break + } + + scriptPkScript, err := btcscript.PayToAddrScript( + scriptAddr) + if err != nil { + t.Errorf("failed to make script pkscript for "+ + "%s: %v", msg, err) + break + } + + sigScript, err := btcscript.SignTxOutput( + btcwire.TestNet3, tx, i, scriptPkScript, + hashType, mkGetKey(map[string]addressToKey{ + address.EncodeAddress(): {key, false}, + }), mkGetScript(map[string][]byte{ + scriptAddr.EncodeAddress(): pkScript, + }), []byte{}) + if err != nil { + t.Errorf("failed to sign output %s: %v", msg, + err) + break + } + + // by the above loop, this should be valid, now sign + // again and merge. + sigScript, err = btcscript.SignTxOutput( + btcwire.TestNet3, tx, i, scriptPkScript, + hashType, mkGetKey(map[string]addressToKey{ + address.EncodeAddress(): {key, false}, + }), mkGetScript(map[string][]byte{ + scriptAddr.EncodeAddress(): pkScript, + }), []byte{}) + if err != nil { + t.Errorf("failed to sign output %s a "+ + "second time: %v", msg, err) + break + } + + err = checkScripts(msg, tx, i, sigScript, scriptPkScript) + if err != nil { + t.Errorf("twice signed script invalid for "+ + "%s: %v", msg, err) + break + } + } + } + + // Pay to Pubkey Hash (compressed) + for _, hashType := range hashTypes { + for i := range tx.TxIn { + msg := fmt.Sprintf("%d:%d", hashType, i) + + key, err := ecdsa.GenerateKey(btcec.S256(), + rand.Reader) + if err != nil { + t.Errorf("failed to make privkey for %s: %v", + msg, err) + break + } + + pk := (*btcec.PublicKey)(&key.PublicKey). + SerializeCompressed() + address, err := btcutil.NewAddressPubKeyHash( + btcutil.Hash160(pk), btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make address for %s: %v", + msg, err) + break + } + + pkScript, err := btcscript.PayToAddrScript(address) + if err != nil { + t.Errorf("failed to make pkscript "+ + "for %s: %v", msg, err) + } + + scriptAddr, err := btcutil.NewAddressScriptHash( + pkScript, btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make p2sh addr for %s: %v", + msg, err) + break + } + + scriptPkScript, err := btcscript.PayToAddrScript( + scriptAddr) + if err != nil { + t.Errorf("failed to make script pkscript for "+ + "%s: %v", msg, err) + break + } + + if err := signAndCheck(msg, tx, i, scriptPkScript, + hashType, + mkGetKey(map[string]addressToKey{ + address.EncodeAddress(): {key, true}, + }), mkGetScript(map[string][]byte{ + scriptAddr.EncodeAddress(): pkScript, + }), []byte{}); err != nil { + t.Error(err) + break + } + } + } + + // Pay to Pubkey Hash (compressed) with duplicate merge + for _, hashType := range hashTypes { + for i := range tx.TxIn { + msg := fmt.Sprintf("%d:%d", hashType, i) + + key, err := ecdsa.GenerateKey(btcec.S256(), + rand.Reader) + if err != nil { + t.Errorf("failed to make privkey for %s: %v", + msg, err) + break + } + + pk := (*btcec.PublicKey)(&key.PublicKey). + SerializeCompressed() + address, err := btcutil.NewAddressPubKeyHash( + btcutil.Hash160(pk), btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make address for %s: %v", + msg, err) + break + } + + pkScript, err := btcscript.PayToAddrScript(address) + if err != nil { + t.Errorf("failed to make pkscript "+ + "for %s: %v", msg, err) + } + + scriptAddr, err := btcutil.NewAddressScriptHash( + pkScript, btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make p2sh addr for %s: %v", + msg, err) + break + } + + scriptPkScript, err := btcscript.PayToAddrScript( + scriptAddr) + if err != nil { + t.Errorf("failed to make script pkscript for "+ + "%s: %v", msg, err) + break + } + + sigScript, err := btcscript.SignTxOutput( + btcwire.TestNet3, tx, i, scriptPkScript, + hashType, mkGetKey(map[string]addressToKey{ + address.EncodeAddress(): {key, true}, + }), mkGetScript(map[string][]byte{ + scriptAddr.EncodeAddress(): pkScript, + }), []byte{}) + if err != nil { + t.Errorf("failed to sign output %s: %v", msg, + err) + break + } + + // by the above loop, this should be valid, now sign + // again and merge. + sigScript, err = btcscript.SignTxOutput( + btcwire.TestNet3, tx, i, scriptPkScript, + hashType, mkGetKey(map[string]addressToKey{ + address.EncodeAddress(): {key, true}, + }), mkGetScript(map[string][]byte{ + scriptAddr.EncodeAddress(): pkScript, + }), []byte{}) + if err != nil { + t.Errorf("failed to sign output %s a "+ + "second time: %v", msg, err) + break + } + + err = checkScripts(msg, tx, i, sigScript, scriptPkScript) + if err != nil { + t.Errorf("twice signed script invalid for "+ + "%s: %v", msg, err) + break + } + } + } + + // Pay to PubKey (uncompressed) + for _, hashType := range hashTypes { + for i := range tx.TxIn { + msg := fmt.Sprintf("%d:%d", hashType, i) + + key, err := ecdsa.GenerateKey(btcec.S256(), + rand.Reader) + if err != nil { + t.Errorf("failed to make privkey for %s: %v", + msg, err) + break + } + + pk := (*btcec.PublicKey)(&key.PublicKey). + SerializeUncompressed() + address, err := btcutil.NewAddressPubKey(pk, + btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make address for %s: %v", + msg, err) + break + } + + pkScript, err := btcscript.PayToAddrScript(address) + if err != nil { + t.Errorf("failed to make pkscript "+ + "for %s: %v", msg, err) + } + + scriptAddr, err := btcutil.NewAddressScriptHash( + pkScript, btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make p2sh addr for %s: %v", + msg, err) + break + } + + scriptPkScript, err := btcscript.PayToAddrScript( + scriptAddr) + if err != nil { + t.Errorf("failed to make script pkscript for "+ + "%s: %v", msg, err) + break + } + + if err := signAndCheck(msg, tx, i, scriptPkScript, + hashType, + mkGetKey(map[string]addressToKey{ + address.EncodeAddress(): {key, false}, + }), mkGetScript(map[string][]byte{ + scriptAddr.EncodeAddress(): pkScript, + }), []byte{}); err != nil { + t.Error(err) + break + } + } + } + + // Pay to PubKey (uncompressed) with duplicate merge + for _, hashType := range hashTypes { + for i := range tx.TxIn { + msg := fmt.Sprintf("%d:%d", hashType, i) + + key, err := ecdsa.GenerateKey(btcec.S256(), + rand.Reader) + if err != nil { + t.Errorf("failed to make privkey for %s: %v", + msg, err) + break + } + + pk := (*btcec.PublicKey)(&key.PublicKey). + SerializeUncompressed() + address, err := btcutil.NewAddressPubKey(pk, + btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make address for %s: %v", + msg, err) + break + } + + pkScript, err := btcscript.PayToAddrScript(address) + if err != nil { + t.Errorf("failed to make pkscript "+ + "for %s: %v", msg, err) + } + + scriptAddr, err := btcutil.NewAddressScriptHash( + pkScript, btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make p2sh addr for %s: %v", + msg, err) + break + } + + scriptPkScript, err := btcscript.PayToAddrScript( + scriptAddr) + if err != nil { + t.Errorf("failed to make script pkscript for "+ + "%s: %v", msg, err) + break + } + + sigScript, err := btcscript.SignTxOutput( + btcwire.TestNet3, tx, i, scriptPkScript, + hashType, mkGetKey(map[string]addressToKey{ + address.EncodeAddress(): {key, false}, + }), mkGetScript(map[string][]byte{ + scriptAddr.EncodeAddress(): pkScript, + }), []byte{}) + if err != nil { + t.Errorf("failed to sign output %s: %v", msg, + err) + break + } + + // by the above loop, this should be valid, now sign + // again and merge. + sigScript, err = btcscript.SignTxOutput( + btcwire.TestNet3, tx, i, scriptPkScript, + hashType, mkGetKey(map[string]addressToKey{ + address.EncodeAddress(): {key, false}, + }), mkGetScript(map[string][]byte{ + scriptAddr.EncodeAddress(): pkScript, + }), []byte{}) + if err != nil { + t.Errorf("failed to sign output %s a "+ + "second time: %v", msg, err) + break + } + + err = checkScripts(msg, tx, i, sigScript, scriptPkScript) + if err != nil { + t.Errorf("twice signed script invalid for "+ + "%s: %v", msg, err) + break + } + } + } + + // Pay to PubKey (compressed) + for _, hashType := range hashTypes { + for i := range tx.TxIn { + msg := fmt.Sprintf("%d:%d", hashType, i) + + key, err := ecdsa.GenerateKey(btcec.S256(), + rand.Reader) + if err != nil { + t.Errorf("failed to make privkey for %s: %v", + msg, err) + break + } + + pk := (*btcec.PublicKey)(&key.PublicKey). + SerializeCompressed() + address, err := btcutil.NewAddressPubKey(pk, + btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make address for %s: %v", + msg, err) + break + } + + pkScript, err := btcscript.PayToAddrScript(address) + if err != nil { + t.Errorf("failed to make pkscript "+ + "for %s: %v", msg, err) + } + + scriptAddr, err := btcutil.NewAddressScriptHash( + pkScript, btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make p2sh addr for %s: %v", + msg, err) + break + } + + scriptPkScript, err := btcscript.PayToAddrScript( + scriptAddr) + if err != nil { + t.Errorf("failed to make script pkscript for "+ + "%s: %v", msg, err) + break + } + + if err := signAndCheck(msg, tx, i, scriptPkScript, + hashType, + mkGetKey(map[string]addressToKey{ + address.EncodeAddress(): {key, true}, + }), mkGetScript(map[string][]byte{ + scriptAddr.EncodeAddress(): pkScript, + }), []byte{}); err != nil { + t.Error(err) + break + } + } + } + + // Pay to PubKey (compressed) + for _, hashType := range hashTypes { + for i := range tx.TxIn { + msg := fmt.Sprintf("%d:%d", hashType, i) + + key, err := ecdsa.GenerateKey(btcec.S256(), + rand.Reader) + if err != nil { + t.Errorf("failed to make privkey for %s: %v", + msg, err) + break + } + + pk := (*btcec.PublicKey)(&key.PublicKey). + SerializeCompressed() + address, err := btcutil.NewAddressPubKey(pk, + btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make address for %s: %v", + msg, err) + break + } + + pkScript, err := btcscript.PayToAddrScript(address) + if err != nil { + t.Errorf("failed to make pkscript "+ + "for %s: %v", msg, err) + } + + scriptAddr, err := btcutil.NewAddressScriptHash( + pkScript, btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make p2sh addr for %s: %v", + msg, err) + break + } + + scriptPkScript, err := btcscript.PayToAddrScript( + scriptAddr) + if err != nil { + t.Errorf("failed to make script pkscript for "+ + "%s: %v", msg, err) + break + } + + sigScript, err := btcscript.SignTxOutput( + btcwire.TestNet3, tx, i, scriptPkScript, + hashType, mkGetKey(map[string]addressToKey{ + address.EncodeAddress(): {key, true}, + }), mkGetScript(map[string][]byte{ + scriptAddr.EncodeAddress(): pkScript, + }), []byte{}) + if err != nil { + t.Errorf("failed to sign output %s: %v", msg, + err) + break + } + + // by the above loop, this should be valid, now sign + // again and merge. + sigScript, err = btcscript.SignTxOutput( + btcwire.TestNet3, tx, i, scriptPkScript, + hashType, mkGetKey(map[string]addressToKey{ + address.EncodeAddress(): {key, true}, + }), mkGetScript(map[string][]byte{ + scriptAddr.EncodeAddress(): pkScript, + }), []byte{}) + if err != nil { + t.Errorf("failed to sign output %s a "+ + "second time: %v", msg, err) + break + } + + err = checkScripts(msg, tx, i, sigScript, scriptPkScript) + if err != nil { + t.Errorf("twice signed script invalid for "+ + "%s: %v", msg, err) + break + } + } + } + + // Basic Multisig + for _, hashType := range hashTypes { + for i := range tx.TxIn { + msg := fmt.Sprintf("%d:%d", hashType, i) + + key1, err := ecdsa.GenerateKey(btcec.S256(), + rand.Reader) + if err != nil { + t.Errorf("failed to make privkey for %s: %v", + msg, err) + break + } + + pk1 := (*btcec.PublicKey)(&key1.PublicKey). + SerializeCompressed() + address1, err := btcutil.NewAddressPubKey(pk1, + btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make address for %s: %v", + msg, err) + break + } + + key2, err := ecdsa.GenerateKey(btcec.S256(), + rand.Reader) + if err != nil { + t.Errorf("failed to make privkey 2 for %s: %v", + msg, err) + break + } + + pk2 := (*btcec.PublicKey)(&key2.PublicKey). + SerializeCompressed() + address2, err := btcutil.NewAddressPubKey(pk2, + btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make address 2 for %s: %v", + msg, err) + break + } + + pkScript, err := btcscript.MultiSigScript( + []*btcutil.AddressPubKey{address1, address2}, + 2) + if err != nil { + t.Errorf("failed to make pkscript "+ + "for %s: %v", msg, err) + } + + scriptAddr, err := btcutil.NewAddressScriptHash( + pkScript, btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make p2sh addr for %s: %v", + msg, err) + break + } + + scriptPkScript, err := btcscript.PayToAddrScript( + scriptAddr) + if err != nil { + t.Errorf("failed to make script pkscript for "+ + "%s: %v", msg, err) + break + } + + if err := signAndCheck(msg, tx, i, scriptPkScript, + hashType, + mkGetKey(map[string]addressToKey{ + address1.EncodeAddress(): {key1, true}, + address2.EncodeAddress(): {key2, true}, + }), mkGetScript(map[string][]byte{ + scriptAddr.EncodeAddress(): pkScript, + }), []byte{}); err != nil { + t.Error(err) + break + } + } + } + + // Two part multisig, sign with one key then the other. + for _, hashType := range hashTypes { + for i := range tx.TxIn { + msg := fmt.Sprintf("%d:%d", hashType, i) + + key1, err := ecdsa.GenerateKey(btcec.S256(), + rand.Reader) + if err != nil { + t.Errorf("failed to make privkey for %s: %v", + msg, err) + break + } + + pk1 := (*btcec.PublicKey)(&key1.PublicKey). + SerializeCompressed() + address1, err := btcutil.NewAddressPubKey(pk1, + btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make address for %s: %v", + msg, err) + break + } + + key2, err := ecdsa.GenerateKey(btcec.S256(), + rand.Reader) + if err != nil { + t.Errorf("failed to make privkey 2 for %s: %v", + msg, err) + break + } + + pk2 := (*btcec.PublicKey)(&key2.PublicKey). + SerializeCompressed() + address2, err := btcutil.NewAddressPubKey(pk2, + btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make address 2 for %s: %v", + msg, err) + break + } + + pkScript, err := btcscript.MultiSigScript( + []*btcutil.AddressPubKey{address1, address2}, + 2) + if err != nil { + t.Errorf("failed to make pkscript "+ + "for %s: %v", msg, err) + } + + scriptAddr, err := btcutil.NewAddressScriptHash( + pkScript, btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make p2sh addr for %s: %v", + msg, err) + break + } + + scriptPkScript, err := btcscript.PayToAddrScript( + scriptAddr) + if err != nil { + t.Errorf("failed to make script pkscript for "+ + "%s: %v", msg, err) + break + } + + sigScript, err := btcscript.SignTxOutput( + btcwire.TestNet3, tx, i, scriptPkScript, + hashType, mkGetKey(map[string]addressToKey{ + address1.EncodeAddress(): {key1, true}, + }), mkGetScript(map[string][]byte{ + scriptAddr.EncodeAddress(): pkScript, + }), []byte{}) + if err != nil { + t.Errorf("failed to sign output %s: %v", msg, + err) + break + } + + // Only 1 out of 2 signed, this *should* fail. + if checkScripts(msg, tx, i, sigScript, + scriptPkScript) == nil { + t.Errorf("part signed script valid for %s", msg) + break + } + + // Sign with the other key and merge + sigScript, err = btcscript.SignTxOutput( + btcwire.TestNet3, tx, i, scriptPkScript, + hashType, mkGetKey(map[string]addressToKey{ + address2.EncodeAddress(): {key2, true}, + }), mkGetScript(map[string][]byte{ + scriptAddr.EncodeAddress(): pkScript, + }), sigScript) + if err != nil { + t.Errorf("failed to sign output %s: %v", msg, err) + break + } + + err = checkScripts(msg, tx, i, sigScript, + scriptPkScript) + if err != nil { + t.Errorf("fully signed script invalid for "+ + "%s: %v", msg, err) + break + } + } + } + + // Two part multisig, sign with one key then both, check key dedup + // correctly. + for _, hashType := range hashTypes { + for i := range tx.TxIn { + msg := fmt.Sprintf("%d:%d", hashType, i) + + key1, err := ecdsa.GenerateKey(btcec.S256(), + rand.Reader) + if err != nil { + t.Errorf("failed to make privkey for %s: %v", + msg, err) + break + } + + pk1 := (*btcec.PublicKey)(&key1.PublicKey). + SerializeCompressed() + address1, err := btcutil.NewAddressPubKey(pk1, + btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make address for %s: %v", + msg, err) + break + } + + key2, err := ecdsa.GenerateKey(btcec.S256(), + rand.Reader) + if err != nil { + t.Errorf("failed to make privkey 2 for %s: %v", + msg, err) + break + } + + pk2 := (*btcec.PublicKey)(&key2.PublicKey). + SerializeCompressed() + address2, err := btcutil.NewAddressPubKey(pk2, + btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make address 2 for %s: %v", + msg, err) + break + } + + pkScript, err := btcscript.MultiSigScript( + []*btcutil.AddressPubKey{address1, address2}, + 2) + if err != nil { + t.Errorf("failed to make pkscript "+ + "for %s: %v", msg, err) + } + + scriptAddr, err := btcutil.NewAddressScriptHash( + pkScript, btcwire.TestNet3) + if err != nil { + t.Errorf("failed to make p2sh addr for %s: %v", + msg, err) + break + } + + scriptPkScript, err := btcscript.PayToAddrScript( + scriptAddr) + if err != nil { + t.Errorf("failed to make script pkscript for "+ + "%s: %v", msg, err) + break + } + + sigScript, err := btcscript.SignTxOutput( + btcwire.TestNet3, tx, i, scriptPkScript, + hashType, mkGetKey(map[string]addressToKey{ + address1.EncodeAddress(): {key1, true}, + }), mkGetScript(map[string][]byte{ + scriptAddr.EncodeAddress(): pkScript, + }), []byte{}) + if err != nil { + t.Errorf("failed to sign output %s: %v", msg, + err) + break + } + + // Only 1 out of 2 signed, this *should* fail. + if checkScripts(msg, tx, i, sigScript, + scriptPkScript) == nil { + t.Errorf("part signed script valid for %s", msg) + break + } + + // Sign with the other key and merge + sigScript, err = btcscript.SignTxOutput( + btcwire.TestNet3, tx, i, scriptPkScript, + hashType, mkGetKey(map[string]addressToKey{ + address1.EncodeAddress(): {key1, true}, + address2.EncodeAddress(): {key2, true}, + }), mkGetScript(map[string][]byte{ + scriptAddr.EncodeAddress(): pkScript, + }), sigScript) + if err != nil { + t.Errorf("failed to sign output %s: %v", msg, err) + break + } + + // Now we should pass. + err = checkScripts(msg, tx, i, sigScript, + scriptPkScript) + if err != nil { + t.Errorf("fully signed script invalid for "+ + "%s: %v", msg, err) + break + } + } + } +} diff --git a/test_coverage.txt b/test_coverage.txt index 51ea818b..5c92a4bd 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -1,8 +1,9 @@ github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 100.00% (60/60) +github.com/conformal/btcscript/script.go calcScriptHash 100.00% (39/39) github.com/conformal/btcscript/script.go Script.Step 100.00% (37/37) -github.com/conformal/btcscript/opcode.go opcodeCheckSig 100.00% (29/29) github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (29/29) +github.com/conformal/btcscript/opcode.go opcodeCheckSig 100.00% (29/29) github.com/conformal/btcscript/address.go ExtractPkScriptAddrs 100.00% (27/27) github.com/conformal/btcscript/script.go CalcScriptInfo 100.00% (25/25) github.com/conformal/btcscript/script.go NewScript 100.00% (23/23) @@ -12,160 +13,169 @@ github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddData 100.00% github.com/conformal/btcscript/opcode.go parsedOpcode.disabled 100.00% (17/17) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (16/16) github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (15/15) -github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (15/15) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) -github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (13/13) -github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) -github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) -github.com/conformal/btcscript/script.go typeOfScript 100.00% (11/11) +github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) +github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) github.com/conformal/btcscript/script.go PayToAddrScript 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) -github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) +github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) +github.com/conformal/btcscript/script.go typeOfScript 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) +github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) +github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) +github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) +github.com/conformal/btcscript/script.go SignatureScript 100.00% (9/9) +github.com/conformal/btcscript/script.go Script.CheckErrorCondition 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) -github.com/conformal/btcscript/script.go Script.CheckErrorCondition 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) -github.com/conformal/btcscript/script.go Script.Execute 100.00% (8/8) -github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) -github.com/conformal/btcscript/script.go MultiSigScript 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddInt64 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddUint64 100.00% (7/7) -github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) +github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) +github.com/conformal/btcscript/script.go MultiSigScript 100.00% (8/8) +github.com/conformal/btcscript/script.go Script.Execute 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) -github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) +github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddInt64 100.00% (7/7) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddUint64 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) +github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodePick 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 100.00% (4/4) +github.com/conformal/btcscript/opcode.go parsedOpcode.alwaysIllegal 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) +github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) +github.com/conformal/btcscript/script.go @1320:17 100.00% (4/4) +github.com/conformal/btcscript/script.go getStack 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) github.com/conformal/btcscript/script.go isNullData 100.00% (4/4) github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/script.go getStack 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) -github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) -github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) -github.com/conformal/btcscript/opcode.go parsedOpcode.alwaysIllegal 100.00% (4/4) -github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) github.com/conformal/btcscript/script.go ScriptClass.String 100.00% (3/3) +github.com/conformal/btcscript/script.go isSmallInt 100.00% (3/3) +github.com/conformal/btcscript/script.go setStack 100.00% (3/3) github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) github.com/conformal/btcscript/script.go asSmallInt 100.00% (3/3) -github.com/conformal/btcscript/script.go setStack 100.00% (3/3) -github.com/conformal/btcscript/script.go isSmallInt 100.00% (3/3) -github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) -github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) -github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddOp 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Reset 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) -github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) -github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) -github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) +github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) +github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddOp 100.00% (2/2) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Reset 100.00% (2/2) +github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/conformal/btcscript/log.go init 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) -github.com/conformal/btcscript/script.go payToPubKeyHashScript 100.00% (1/1) -github.com/conformal/btcscript/script.go payToScriptHashScript 100.00% (1/1) -github.com/conformal/btcscript/script.go payToPubKeyScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) -github.com/conformal/btcscript/scriptbuilder.go NewScriptBuilder 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/log.go init 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) -github.com/conformal/btcscript/opcode.go init 100.00% (1/1) -github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) -github.com/conformal/btcscript/script.go calcScriptHash 97.44% (38/39) +github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go init 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) +github.com/conformal/btcscript/script.go payToPubKeyHashScript 100.00% (1/1) +github.com/conformal/btcscript/script.go payToScriptHashScript 100.00% (1/1) +github.com/conformal/btcscript/script.go payToPubKeyScript 100.00% (1/1) +github.com/conformal/btcscript/script.go signTxOutput 100.00% (1/1) +github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) +github.com/conformal/btcscript/script.go KeyClosure.GetKey 100.00% (1/1) +github.com/conformal/btcscript/script.go ScriptClosure.GetScript 100.00% (1/1) +github.com/conformal/btcscript/scriptbuilder.go NewScriptBuilder 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) +github.com/conformal/btcscript/script.go mergeScripts 95.00% (19/20) github.com/conformal/btcscript/script.go canonicalPush 92.86% (13/14) -github.com/conformal/btcscript/script.go unparseScript 85.71% (6/7) +github.com/conformal/btcscript/script.go signMultiSig 92.86% (13/14) +github.com/conformal/btcscript/script.go mergeMultiSig 88.10% (37/42) +github.com/conformal/btcscript/script.go signTxOutputCustomReader 87.50% (7/8) github.com/conformal/btcscript/script.go expectedInputs 85.71% (6/7) +github.com/conformal/btcscript/script.go unparseScript 85.71% (6/7) +github.com/conformal/btcscript/script.go SignTxOutput 80.00% (12/15) +github.com/conformal/btcscript/script.go p2pkSignatureScript 75.00% (3/4) github.com/conformal/btcscript/script.go IsPushOnlyScript 75.00% (3/4) github.com/conformal/btcscript/script.go HasCanonicalPushes 71.43% (5/7) +github.com/conformal/btcscript/script.go sign 69.23% (18/26) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/10) github.com/conformal/btcscript/script.go CalcMultiSigStats 0.00% (0/8) github.com/conformal/btcscript/script.go @577:34 0.00% (0/6) github.com/conformal/btcscript/script.go @565:34 0.00% (0/4) github.com/conformal/btcscript/script.go @610:34 0.00% (0/3) -github.com/conformal/btcscript/log.go UseLogger 0.00% (0/1) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) github.com/conformal/btcscript/opcode.go @1803:33 0.00% (0/1) github.com/conformal/btcscript/opcode.go opcodeDisabled 0.00% (0/1) -github.com/conformal/btcscript --------------------------- 96.23% (1073/1115) +github.com/conformal/btcscript/log.go UseLogger 0.00% (0/1) +github.com/conformal/btcscript -------------------------- 95.10% (1183/1244) From 27e1ad758bb0a88347436011624e2d7ad459f0fb Mon Sep 17 00:00:00 2001 From: David Hill Date: Thu, 8 May 2014 13:14:01 -0400 Subject: [PATCH 129/174] Add new function PushedData. PushedData returns an array of byte slices containing any pushed data found in the passed script. This includes OP_0, but not OP_1 - OP_16. help from and ok @owainga --- script.go | 18 ++++++ script_test.go | 60 ++++++++++++++++++ test_coverage.txt | 157 +++++++++++++++++++++++----------------------- 3 files changed, 157 insertions(+), 78 deletions(-) diff --git a/script.go b/script.go index 21e91089..d254af97 100644 --- a/script.go +++ b/script.go @@ -1616,3 +1616,21 @@ func CalcMultiSigStats(script []byte) (int, int, error) { numPubKeys := asSmallInt(pops[len(pops)-2].opcode) return numPubKeys, numSigs, nil } + +// PushedData returns an array of byte slices containing any pushed data found +// in the passed script. This includes OP_0, but not OP_1 - OP_16. +func PushedData(script []byte) ([][]byte, error) { + pops, err := parseScript(script) + if err != nil { + return nil, err + } + var data [][]byte + for _, pop := range pops { + if pop.data != nil { + data = append(data, pop.data) + } else if pop.opcode.value == OP_0 { + data = append(data, []byte{}) + } + } + return data, nil +} diff --git a/script_test.go b/script_test.go index 54b98b3f..e119f56b 100644 --- a/script_test.go +++ b/script_test.go @@ -18,6 +18,66 @@ import ( "testing" ) +func TestPushedData(t *testing.T) { + var tests = []struct { + in []byte + out [][]byte + valid bool + }{ + { + []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, + [][]byte{{}, {}}, + true, + }, + { + btcscript.NewScriptBuilder().AddInt64(16777216).AddInt64(10000000).Script(), + [][]byte{ + {0x00, 0x00, 0x00, 0x01}, // 16777216 + {0x80, 0x96, 0x98, 0x00}, // 10000000 + }, + true, + }, + { + btcscript.NewScriptBuilder().AddOp(btcscript.OP_DUP).AddOp(btcscript.OP_HASH160). + AddData([]byte("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem")).AddOp(btcscript.OP_EQUALVERIFY). + AddOp(btcscript.OP_CHECKSIG).Script(), + [][]byte{ + // 17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem + { + 0x31, 0x37, 0x56, 0x5a, 0x4e, 0x58, 0x31, 0x53, 0x4e, 0x35, + 0x4e, 0x74, 0x4b, 0x61, 0x38, 0x55, 0x51, 0x46, 0x78, 0x77, + 0x51, 0x62, 0x46, 0x65, 0x46, 0x63, 0x33, 0x69, 0x71, 0x52, + 0x59, 0x68, 0x65, 0x6d, + }, + }, + true, + }, + { + btcscript.NewScriptBuilder().AddOp(btcscript.OP_PUSHDATA4).AddInt64(1000). + AddOp(btcscript.OP_EQUAL).Script(), + [][]byte{}, + false, + }, + } + + for x, test := range tests { + pushedData, err := btcscript.PushedData(test.in) + if test.valid && err != nil { + t.Errorf("TestPushedData failed test #%d: %v\n", x, err) + continue + } else if !test.valid && err == nil { + t.Errorf("TestPushedData failed test #%d: test should be invalid\n", x) + continue + } + for x, data := range pushedData { + if !bytes.Equal(data, test.out[x]) { + t.Errorf("TestPushedData failed test #%d: want: %x got: %x\n", + x, test.out[x], data) + } + } + } +} + func TestStandardPushes(t *testing.T) { for i := 0; i < 1000; i++ { builder := btcscript.NewScriptBuilder() diff --git a/test_coverage.txt b/test_coverage.txt index 5c92a4bd..aa6dc207 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -33,129 +33,130 @@ github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10 github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) +github.com/conformal/btcscript/script.go PushedData 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) github.com/conformal/btcscript/script.go SignatureScript 100.00% (9/9) -github.com/conformal/btcscript/script.go Script.CheckErrorCondition 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) +github.com/conformal/btcscript/script.go Script.CheckErrorCondition 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) +github.com/conformal/btcscript/script.go Script.Execute 100.00% (8/8) +github.com/conformal/btcscript/script.go MultiSigScript 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) -github.com/conformal/btcscript/script.go MultiSigScript 100.00% (8/8) -github.com/conformal/btcscript/script.go Script.Execute 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) -github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddInt64 100.00% (7/7) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddUint64 100.00% (7/7) +github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddUint64 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodePick 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodePick 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 100.00% (4/4) -github.com/conformal/btcscript/opcode.go parsedOpcode.alwaysIllegal 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) -github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) -github.com/conformal/btcscript/script.go @1320:17 100.00% (4/4) -github.com/conformal/btcscript/script.go getStack 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 100.00% (4/4) +github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) github.com/conformal/btcscript/script.go isNullData 100.00% (4/4) github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) +github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) +github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) +github.com/conformal/btcscript/opcode.go parsedOpcode.alwaysIllegal 100.00% (4/4) +github.com/conformal/btcscript/script.go getStack 100.00% (4/4) +github.com/conformal/btcscript/script.go @1320:17 100.00% (4/4) +github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) +github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) +github.com/conformal/btcscript/script.go asSmallInt 100.00% (3/3) +github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) +github.com/conformal/btcscript/script.go setStack 100.00% (3/3) github.com/conformal/btcscript/script.go ScriptClass.String 100.00% (3/3) github.com/conformal/btcscript/script.go isSmallInt 100.00% (3/3) -github.com/conformal/btcscript/script.go setStack 100.00% (3/3) -github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) -github.com/conformal/btcscript/script.go asSmallInt 100.00% (3/3) -github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) -github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddOp 100.00% (2/2) +github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Reset 100.00% (2/2) -github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) github.com/conformal/btcscript/log.go init 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) +github.com/conformal/btcscript/script.go signTxOutput 100.00% (1/1) +github.com/conformal/btcscript/script.go payToPubKeyScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go init 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) github.com/conformal/btcscript/script.go payToPubKeyHashScript 100.00% (1/1) github.com/conformal/btcscript/script.go payToScriptHashScript 100.00% (1/1) -github.com/conformal/btcscript/script.go payToPubKeyScript 100.00% (1/1) -github.com/conformal/btcscript/script.go signTxOutput 100.00% (1/1) +github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) +github.com/conformal/btcscript/scriptbuilder.go NewScriptBuilder 100.00% (1/1) +github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) github.com/conformal/btcscript/script.go KeyClosure.GetKey 100.00% (1/1) github.com/conformal/btcscript/script.go ScriptClosure.GetScript 100.00% (1/1) -github.com/conformal/btcscript/scriptbuilder.go NewScriptBuilder 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) github.com/conformal/btcscript/script.go mergeScripts 95.00% (19/20) github.com/conformal/btcscript/script.go canonicalPush 92.86% (13/14) github.com/conformal/btcscript/script.go signMultiSig 92.86% (13/14) @@ -164,8 +165,8 @@ github.com/conformal/btcscript/script.go signTxOutputCustomReader 87.50% (7/8) github.com/conformal/btcscript/script.go expectedInputs 85.71% (6/7) github.com/conformal/btcscript/script.go unparseScript 85.71% (6/7) github.com/conformal/btcscript/script.go SignTxOutput 80.00% (12/15) -github.com/conformal/btcscript/script.go p2pkSignatureScript 75.00% (3/4) github.com/conformal/btcscript/script.go IsPushOnlyScript 75.00% (3/4) +github.com/conformal/btcscript/script.go p2pkSignatureScript 75.00% (3/4) github.com/conformal/btcscript/script.go HasCanonicalPushes 71.43% (5/7) github.com/conformal/btcscript/script.go sign 69.23% (18/26) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/10) @@ -173,9 +174,9 @@ github.com/conformal/btcscript/script.go CalcMultiSigStats 0.00% (0/8) github.com/conformal/btcscript/script.go @577:34 0.00% (0/6) github.com/conformal/btcscript/script.go @565:34 0.00% (0/4) github.com/conformal/btcscript/script.go @610:34 0.00% (0/3) +github.com/conformal/btcscript/log.go UseLogger 0.00% (0/1) +github.com/conformal/btcscript/opcode.go opcodeDisabled 0.00% (0/1) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) github.com/conformal/btcscript/opcode.go @1803:33 0.00% (0/1) -github.com/conformal/btcscript/opcode.go opcodeDisabled 0.00% (0/1) -github.com/conformal/btcscript/log.go UseLogger 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 95.10% (1183/1244) +github.com/conformal/btcscript -------------------------- 95.14% (1193/1254) From be325b9d9c69f330d32143a3915d665e65b0066d Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Tue, 27 May 2014 17:41:28 -0500 Subject: [PATCH 130/174] Update API for btcnet and btcutil changes. ok @davecgh --- address.go | 4 +- address_test.go | 11 ++-- script.go | 7 +-- script_test.go | 127 +++++++++++++++++++++++----------------------- test_coverage.txt | 8 +-- 5 files changed, 80 insertions(+), 77 deletions(-) diff --git a/address.go b/address.go index b23f1b32..979abf0e 100644 --- a/address.go +++ b/address.go @@ -5,15 +5,15 @@ package btcscript import ( + "github.com/conformal/btcnet" "github.com/conformal/btcutil" - "github.com/conformal/btcwire" ) // ExtractPkScriptAddrs returns the type of script, addresses and required // signatures associated with the passed PkScript. Note that it only works for // 'standard' transaction script types. Any data such as public keys which are // invalid are omitted from the results. -func ExtractPkScriptAddrs(pkScript []byte, net btcwire.BitcoinNet) (ScriptClass, []btcutil.Address, int, error) { +func ExtractPkScriptAddrs(pkScript []byte, net *btcnet.Params) (ScriptClass, []btcutil.Address, int, error) { var addrs []btcutil.Address var requiredSigs int diff --git a/address_test.go b/address_test.go index 698fcce5..f1d546b3 100644 --- a/address_test.go +++ b/address_test.go @@ -5,9 +5,9 @@ package btcscript_test import ( "encoding/hex" + "github.com/conformal/btcnet" "github.com/conformal/btcscript" "github.com/conformal/btcutil" - "github.com/conformal/btcwire" "reflect" "testing" ) @@ -30,7 +30,8 @@ func decodeHex(hexStr string) []byte { // the tests as a helper since the only way it can fail is if there is an error // in the test source code. func newAddressPubKey(serializedPubKey []byte) btcutil.Address { - addr, err := btcutil.NewAddressPubKey(serializedPubKey, btcwire.MainNet) + addr, err := btcutil.NewAddressPubKey(serializedPubKey, + &btcnet.MainNetParams) if err != nil { panic("invalid public key in test source") } @@ -43,7 +44,7 @@ func newAddressPubKey(serializedPubKey []byte) btcutil.Address { // as a helper since the only way it can fail is if there is an error in the // test source code. func newAddressPubKeyHash(pkHash []byte) btcutil.Address { - addr, err := btcutil.NewAddressPubKeyHash(pkHash, btcwire.MainNet) + addr, err := btcutil.NewAddressPubKeyHash(pkHash, &btcnet.MainNetParams) if err != nil { panic("invalid public key hash in test source") } @@ -57,7 +58,7 @@ func newAddressPubKeyHash(pkHash []byte) btcutil.Address { // test source code. func newAddressScriptHash(scriptHash []byte) btcutil.Address { addr, err := btcutil.NewAddressScriptHashFromHash(scriptHash, - btcwire.MainNet) + &btcnet.MainNetParams) if err != nil { panic("invalid script hash in test source") } @@ -338,7 +339,7 @@ func TestExtractPkScriptAddrs(t *testing.T) { t.Logf("Running %d tests.", len(tests)) for i, test := range tests { class, addrs, reqSigs, err := btcscript.ExtractPkScriptAddrs( - test.script, btcwire.MainNet) + test.script, &btcnet.MainNetParams) if err != nil { } diff --git a/script.go b/script.go index d254af97..945f3b4f 100644 --- a/script.go +++ b/script.go @@ -12,6 +12,7 @@ import ( "errors" "fmt" "github.com/conformal/btcec" + "github.com/conformal/btcnet" "github.com/conformal/btcutil" "github.com/conformal/btcwire" "github.com/davecgh/go-spew/spew" @@ -1168,7 +1169,7 @@ func signMultiSig(tx *btcwire.MsgTx, idx int, subScript []byte, hashType byte, return builder.Script(), signed == nRequired } -func sign(net btcwire.BitcoinNet, tx *btcwire.MsgTx, idx int, subScript []byte, +func sign(net *btcnet.Params, tx *btcwire.MsgTx, idx int, subScript []byte, hashType byte, kdb KeyDB, sdb ScriptDB) ([]byte, ScriptClass, []btcutil.Address, int, error) { @@ -1232,7 +1233,7 @@ func sign(net btcwire.BitcoinNet, tx *btcwire.MsgTx, idx int, subScript []byte, // The return value is the best effort merging of the two scripts. Calling this // function with addresses, class and nrequired that do not match pkScript is // an error and results in undefined behaviour. -func mergeScripts(net btcwire.BitcoinNet, tx *btcwire.MsgTx, idx int, +func mergeScripts(net *btcnet.Params, tx *btcwire.MsgTx, idx int, pkScript []byte, class ScriptClass, addresses []btcutil.Address, nRequired int, sigScript, prevScript []byte) []byte { @@ -1444,7 +1445,7 @@ func (sc ScriptClosure) GetScript(address btcutil.Address) ([]byte, error) { // getScript. If previousScript is provided then the results in previousScript // will be merged in a type-dependant manner with the newly generated. // signature script. -func SignTxOutput(net btcwire.BitcoinNet, tx *btcwire.MsgTx, idx int, +func SignTxOutput(net *btcnet.Params, tx *btcwire.MsgTx, idx int, pkScript []byte, hashType byte, kdb KeyDB, sdb ScriptDB, previousScript []byte) ([]byte, error) { diff --git a/script_test.go b/script_test.go index e119f56b..40bde3ee 100644 --- a/script_test.go +++ b/script_test.go @@ -11,6 +11,7 @@ import ( "errors" "fmt" "github.com/conformal/btcec" + "github.com/conformal/btcnet" "github.com/conformal/btcscript" "github.com/conformal/btcutil" "github.com/conformal/btcwire" @@ -2924,7 +2925,7 @@ func (b *bogusAddress) ScriptAddress() []byte { } // IsForNet lies blatantly to satisfy the btcutil.Address interface. -func (b *bogusAddress) IsForNet(btcwire.BitcoinNet) bool { +func (b *bogusAddress) IsForNet(net *btcnet.Params) bool { return true // why not? } @@ -2933,7 +2934,7 @@ func TestPayToAddrScript(t *testing.T) { p2pkhMain, err := btcutil.NewAddressPubKeyHash([]byte{ 0xe3, 0x4c, 0xce, 0x70, 0xc8, 0x63, 0x73, 0x27, 0x3e, 0xfc, 0xc5, 0x4c, 0xe7, 0xd2, 0xa4, 0x91, 0xbb, 0x4a, 0x0e, 0x84, - }, btcwire.MainNet) + }, &btcnet.MainNetParams) if err != nil { t.Errorf("Unable to create public key hash address: %v", err) return @@ -2944,7 +2945,7 @@ func TestPayToAddrScript(t *testing.T) { p2shMain, _ := btcutil.NewAddressScriptHashFromHash([]byte{ 0xe8, 0xc3, 0x00, 0xc8, 0x79, 0x86, 0xef, 0xa8, 0x4c, 0x37, 0xc0, 0x51, 0x99, 0x29, 0x01, 0x9e, 0xf8, 0x6e, 0xb5, 0xb4, - }, btcwire.MainNet) + }, &btcnet.MainNetParams) if err != nil { t.Errorf("Unable to create script hash address: %v", err) return @@ -2955,7 +2956,7 @@ func TestPayToAddrScript(t *testing.T) { 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, - 0x52, 0xc6, 0xb4}, btcwire.MainNet) + 0x52, 0xc6, 0xb4}, &btcnet.MainNetParams) if err != nil { t.Errorf("Unable to create pubkey address (compressed): %v", err) @@ -2965,7 +2966,7 @@ func TestPayToAddrScript(t *testing.T) { 0x03, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, - 0xb1, 0x6e, 0x65}, btcwire.MainNet) + 0xb1, 0x6e, 0x65}, &btcnet.MainNetParams) if err != nil { t.Errorf("Unable to create pubkey address (compressed 2): %v", err) @@ -2979,7 +2980,7 @@ func TestPayToAddrScript(t *testing.T) { 0x90, 0x9a, 0x5c, 0xb2, 0xe0, 0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, - 0xf6, 0x56, 0xb4, 0x12, 0xa3}, btcwire.MainNet) + 0xf6, 0x56, 0xb4, 0x12, 0xa3}, &btcnet.MainNetParams) if err != nil { t.Errorf("Unable to create pubkey address (uncompressed): %v", err) @@ -3088,7 +3089,7 @@ func TestMultiSigScript(t *testing.T) { 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, - 0x52, 0xc6, 0xb4}, btcwire.MainNet) + 0x52, 0xc6, 0xb4}, &btcnet.MainNetParams) if err != nil { t.Errorf("Unable to create pubkey address (compressed): %v", err) @@ -3098,7 +3099,7 @@ func TestMultiSigScript(t *testing.T) { 0x03, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, - 0xb1, 0x6e, 0x65}, btcwire.MainNet) + 0xb1, 0x6e, 0x65}, &btcnet.MainNetParams) if err != nil { t.Errorf("Unable to create pubkey address (compressed 2): %v", err) @@ -3112,7 +3113,7 @@ func TestMultiSigScript(t *testing.T) { 0x90, 0x9a, 0x5c, 0xb2, 0xe0, 0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, - 0xf6, 0x56, 0xb4, 0x12, 0xa3}, btcwire.MainNet) + 0xf6, 0x56, 0xb4, 0x12, 0xa3}, &btcnet.MainNetParams) if err != nil { t.Errorf("Unable to create pubkey address (uncompressed): %v", err) @@ -3235,7 +3236,7 @@ func signAndCheck(msg string, tx *btcwire.MsgTx, idx int, pkScript []byte, previousScript []byte) error { sigScript, err := btcscript.SignTxOutput( - btcwire.TestNet3, tx, idx, pkScript, hashType, + &btcnet.TestNet3Params, tx, idx, pkScript, hashType, kdb, sdb, []byte{}) if err != nil { return fmt.Errorf("failed to sign output %s: %v", msg, err) @@ -3369,7 +3370,7 @@ func TestSignTxOutput(t *testing.T) { pk := (*btcec.PublicKey)(&key.PublicKey). SerializeUncompressed() address, err := btcutil.NewAddressPubKeyHash( - btcutil.Hash160(pk), btcwire.TestNet3) + btcutil.Hash160(pk), &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) @@ -3407,7 +3408,7 @@ func TestSignTxOutput(t *testing.T) { pk := (*btcec.PublicKey)(&key.PublicKey). SerializeUncompressed() address, err := btcutil.NewAddressPubKeyHash( - btcutil.Hash160(pk), btcwire.TestNet3) + btcutil.Hash160(pk), &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) @@ -3421,7 +3422,7 @@ func TestSignTxOutput(t *testing.T) { } sigScript, err := btcscript.SignTxOutput( - btcwire.TestNet3, tx, i, pkScript, + &btcnet.TestNet3Params, tx, i, pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, }), mkGetScript(nil), []byte{}) @@ -3434,7 +3435,7 @@ func TestSignTxOutput(t *testing.T) { // by the above loop, this should be valid, now sign // again and merge. sigScript, err = btcscript.SignTxOutput( - btcwire.TestNet3, tx, i, pkScript, + &btcnet.TestNet3Params, tx, i, pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, }), mkGetScript(nil), sigScript) @@ -3469,7 +3470,7 @@ func TestSignTxOutput(t *testing.T) { pk := (*btcec.PublicKey)(&key.PublicKey). SerializeCompressed() address, err := btcutil.NewAddressPubKeyHash( - btcutil.Hash160(pk), btcwire.TestNet3) + btcutil.Hash160(pk), &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) @@ -3508,7 +3509,7 @@ func TestSignTxOutput(t *testing.T) { pk := (*btcec.PublicKey)(&key.PublicKey). SerializeCompressed() address, err := btcutil.NewAddressPubKeyHash( - btcutil.Hash160(pk), btcwire.TestNet3) + btcutil.Hash160(pk), &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) @@ -3522,7 +3523,7 @@ func TestSignTxOutput(t *testing.T) { } sigScript, err := btcscript.SignTxOutput( - btcwire.TestNet3, tx, i, pkScript, + &btcnet.TestNet3Params, tx, i, pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, }), mkGetScript(nil), []byte{}) @@ -3535,7 +3536,7 @@ func TestSignTxOutput(t *testing.T) { // by the above loop, this should be valid, now sign // again and merge. sigScript, err = btcscript.SignTxOutput( - btcwire.TestNet3, tx, i, pkScript, + &btcnet.TestNet3Params, tx, i, pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, }), mkGetScript(nil), sigScript) @@ -3570,7 +3571,7 @@ func TestSignTxOutput(t *testing.T) { pk := (*btcec.PublicKey)(&key.PublicKey). SerializeUncompressed() address, err := btcutil.NewAddressPubKey(pk, - btcwire.TestNet3) + &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) @@ -3609,7 +3610,7 @@ func TestSignTxOutput(t *testing.T) { pk := (*btcec.PublicKey)(&key.PublicKey). SerializeUncompressed() address, err := btcutil.NewAddressPubKey(pk, - btcwire.TestNet3) + &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) @@ -3623,7 +3624,7 @@ func TestSignTxOutput(t *testing.T) { } sigScript, err := btcscript.SignTxOutput( - btcwire.TestNet3, tx, i, pkScript, + &btcnet.TestNet3Params, tx, i, pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, }), mkGetScript(nil), []byte{}) @@ -3636,7 +3637,7 @@ func TestSignTxOutput(t *testing.T) { // by the above loop, this should be valid, now sign // again and merge. sigScript, err = btcscript.SignTxOutput( - btcwire.TestNet3, tx, i, pkScript, + &btcnet.TestNet3Params, tx, i, pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, }), mkGetScript(nil), sigScript) @@ -3671,7 +3672,7 @@ func TestSignTxOutput(t *testing.T) { pk := (*btcec.PublicKey)(&key.PublicKey). SerializeCompressed() address, err := btcutil.NewAddressPubKey(pk, - btcwire.TestNet3) + &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) @@ -3710,7 +3711,7 @@ func TestSignTxOutput(t *testing.T) { pk := (*btcec.PublicKey)(&key.PublicKey). SerializeCompressed() address, err := btcutil.NewAddressPubKey(pk, - btcwire.TestNet3) + &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) @@ -3724,7 +3725,7 @@ func TestSignTxOutput(t *testing.T) { } sigScript, err := btcscript.SignTxOutput( - btcwire.TestNet3, tx, i, pkScript, + &btcnet.TestNet3Params, tx, i, pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, }), mkGetScript(nil), []byte{}) @@ -3737,7 +3738,7 @@ func TestSignTxOutput(t *testing.T) { // by the above loop, this should be valid, now sign // again and merge. sigScript, err = btcscript.SignTxOutput( - btcwire.TestNet3, tx, i, pkScript, + &btcnet.TestNet3Params, tx, i, pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, }), mkGetScript(nil), sigScript) @@ -3772,7 +3773,7 @@ func TestSignTxOutput(t *testing.T) { pk := (*btcec.PublicKey)(&key.PublicKey). SerializeUncompressed() address, err := btcutil.NewAddressPubKeyHash( - btcutil.Hash160(pk), btcwire.TestNet3) + btcutil.Hash160(pk), &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) @@ -3787,7 +3788,7 @@ func TestSignTxOutput(t *testing.T) { } scriptAddr, err := btcutil.NewAddressScriptHash( - pkScript, btcwire.TestNet3) + pkScript, &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make p2sh addr for %s: %v", msg, err) @@ -3830,7 +3831,7 @@ func TestSignTxOutput(t *testing.T) { pk := (*btcec.PublicKey)(&key.PublicKey). SerializeUncompressed() address, err := btcutil.NewAddressPubKeyHash( - btcutil.Hash160(pk), btcwire.TestNet3) + btcutil.Hash160(pk), &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) @@ -3845,7 +3846,7 @@ func TestSignTxOutput(t *testing.T) { } scriptAddr, err := btcutil.NewAddressScriptHash( - pkScript, btcwire.TestNet3) + pkScript, &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make p2sh addr for %s: %v", msg, err) @@ -3861,7 +3862,7 @@ func TestSignTxOutput(t *testing.T) { } sigScript, err := btcscript.SignTxOutput( - btcwire.TestNet3, tx, i, scriptPkScript, + &btcnet.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, }), mkGetScript(map[string][]byte{ @@ -3876,7 +3877,7 @@ func TestSignTxOutput(t *testing.T) { // by the above loop, this should be valid, now sign // again and merge. sigScript, err = btcscript.SignTxOutput( - btcwire.TestNet3, tx, i, scriptPkScript, + &btcnet.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, }), mkGetScript(map[string][]byte{ @@ -3913,7 +3914,7 @@ func TestSignTxOutput(t *testing.T) { pk := (*btcec.PublicKey)(&key.PublicKey). SerializeCompressed() address, err := btcutil.NewAddressPubKeyHash( - btcutil.Hash160(pk), btcwire.TestNet3) + btcutil.Hash160(pk), &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) @@ -3927,7 +3928,7 @@ func TestSignTxOutput(t *testing.T) { } scriptAddr, err := btcutil.NewAddressScriptHash( - pkScript, btcwire.TestNet3) + pkScript, &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make p2sh addr for %s: %v", msg, err) @@ -3971,7 +3972,7 @@ func TestSignTxOutput(t *testing.T) { pk := (*btcec.PublicKey)(&key.PublicKey). SerializeCompressed() address, err := btcutil.NewAddressPubKeyHash( - btcutil.Hash160(pk), btcwire.TestNet3) + btcutil.Hash160(pk), &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) @@ -3985,7 +3986,7 @@ func TestSignTxOutput(t *testing.T) { } scriptAddr, err := btcutil.NewAddressScriptHash( - pkScript, btcwire.TestNet3) + pkScript, &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make p2sh addr for %s: %v", msg, err) @@ -4001,7 +4002,7 @@ func TestSignTxOutput(t *testing.T) { } sigScript, err := btcscript.SignTxOutput( - btcwire.TestNet3, tx, i, scriptPkScript, + &btcnet.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, }), mkGetScript(map[string][]byte{ @@ -4016,7 +4017,7 @@ func TestSignTxOutput(t *testing.T) { // by the above loop, this should be valid, now sign // again and merge. sigScript, err = btcscript.SignTxOutput( - btcwire.TestNet3, tx, i, scriptPkScript, + &btcnet.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, }), mkGetScript(map[string][]byte{ @@ -4053,7 +4054,7 @@ func TestSignTxOutput(t *testing.T) { pk := (*btcec.PublicKey)(&key.PublicKey). SerializeUncompressed() address, err := btcutil.NewAddressPubKey(pk, - btcwire.TestNet3) + &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) @@ -4067,7 +4068,7 @@ func TestSignTxOutput(t *testing.T) { } scriptAddr, err := btcutil.NewAddressScriptHash( - pkScript, btcwire.TestNet3) + pkScript, &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make p2sh addr for %s: %v", msg, err) @@ -4111,7 +4112,7 @@ func TestSignTxOutput(t *testing.T) { pk := (*btcec.PublicKey)(&key.PublicKey). SerializeUncompressed() address, err := btcutil.NewAddressPubKey(pk, - btcwire.TestNet3) + &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) @@ -4125,7 +4126,7 @@ func TestSignTxOutput(t *testing.T) { } scriptAddr, err := btcutil.NewAddressScriptHash( - pkScript, btcwire.TestNet3) + pkScript, &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make p2sh addr for %s: %v", msg, err) @@ -4141,7 +4142,7 @@ func TestSignTxOutput(t *testing.T) { } sigScript, err := btcscript.SignTxOutput( - btcwire.TestNet3, tx, i, scriptPkScript, + &btcnet.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, }), mkGetScript(map[string][]byte{ @@ -4156,7 +4157,7 @@ func TestSignTxOutput(t *testing.T) { // by the above loop, this should be valid, now sign // again and merge. sigScript, err = btcscript.SignTxOutput( - btcwire.TestNet3, tx, i, scriptPkScript, + &btcnet.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, }), mkGetScript(map[string][]byte{ @@ -4193,7 +4194,7 @@ func TestSignTxOutput(t *testing.T) { pk := (*btcec.PublicKey)(&key.PublicKey). SerializeCompressed() address, err := btcutil.NewAddressPubKey(pk, - btcwire.TestNet3) + &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) @@ -4207,7 +4208,7 @@ func TestSignTxOutput(t *testing.T) { } scriptAddr, err := btcutil.NewAddressScriptHash( - pkScript, btcwire.TestNet3) + pkScript, &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make p2sh addr for %s: %v", msg, err) @@ -4251,7 +4252,7 @@ func TestSignTxOutput(t *testing.T) { pk := (*btcec.PublicKey)(&key.PublicKey). SerializeCompressed() address, err := btcutil.NewAddressPubKey(pk, - btcwire.TestNet3) + &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) @@ -4265,7 +4266,7 @@ func TestSignTxOutput(t *testing.T) { } scriptAddr, err := btcutil.NewAddressScriptHash( - pkScript, btcwire.TestNet3) + pkScript, &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make p2sh addr for %s: %v", msg, err) @@ -4281,7 +4282,7 @@ func TestSignTxOutput(t *testing.T) { } sigScript, err := btcscript.SignTxOutput( - btcwire.TestNet3, tx, i, scriptPkScript, + &btcnet.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, }), mkGetScript(map[string][]byte{ @@ -4296,7 +4297,7 @@ func TestSignTxOutput(t *testing.T) { // by the above loop, this should be valid, now sign // again and merge. sigScript, err = btcscript.SignTxOutput( - btcwire.TestNet3, tx, i, scriptPkScript, + &btcnet.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, }), mkGetScript(map[string][]byte{ @@ -4333,7 +4334,7 @@ func TestSignTxOutput(t *testing.T) { pk1 := (*btcec.PublicKey)(&key1.PublicKey). SerializeCompressed() address1, err := btcutil.NewAddressPubKey(pk1, - btcwire.TestNet3) + &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) @@ -4351,7 +4352,7 @@ func TestSignTxOutput(t *testing.T) { pk2 := (*btcec.PublicKey)(&key2.PublicKey). SerializeCompressed() address2, err := btcutil.NewAddressPubKey(pk2, - btcwire.TestNet3) + &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make address 2 for %s: %v", msg, err) @@ -4367,7 +4368,7 @@ func TestSignTxOutput(t *testing.T) { } scriptAddr, err := btcutil.NewAddressScriptHash( - pkScript, btcwire.TestNet3) + pkScript, &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make p2sh addr for %s: %v", msg, err) @@ -4412,7 +4413,7 @@ func TestSignTxOutput(t *testing.T) { pk1 := (*btcec.PublicKey)(&key1.PublicKey). SerializeCompressed() address1, err := btcutil.NewAddressPubKey(pk1, - btcwire.TestNet3) + &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) @@ -4430,7 +4431,7 @@ func TestSignTxOutput(t *testing.T) { pk2 := (*btcec.PublicKey)(&key2.PublicKey). SerializeCompressed() address2, err := btcutil.NewAddressPubKey(pk2, - btcwire.TestNet3) + &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make address 2 for %s: %v", msg, err) @@ -4446,7 +4447,7 @@ func TestSignTxOutput(t *testing.T) { } scriptAddr, err := btcutil.NewAddressScriptHash( - pkScript, btcwire.TestNet3) + pkScript, &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make p2sh addr for %s: %v", msg, err) @@ -4462,7 +4463,7 @@ func TestSignTxOutput(t *testing.T) { } sigScript, err := btcscript.SignTxOutput( - btcwire.TestNet3, tx, i, scriptPkScript, + &btcnet.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address1.EncodeAddress(): {key1, true}, }), mkGetScript(map[string][]byte{ @@ -4483,7 +4484,7 @@ func TestSignTxOutput(t *testing.T) { // Sign with the other key and merge sigScript, err = btcscript.SignTxOutput( - btcwire.TestNet3, tx, i, scriptPkScript, + &btcnet.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address2.EncodeAddress(): {key2, true}, }), mkGetScript(map[string][]byte{ @@ -4521,7 +4522,7 @@ func TestSignTxOutput(t *testing.T) { pk1 := (*btcec.PublicKey)(&key1.PublicKey). SerializeCompressed() address1, err := btcutil.NewAddressPubKey(pk1, - btcwire.TestNet3) + &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) @@ -4539,7 +4540,7 @@ func TestSignTxOutput(t *testing.T) { pk2 := (*btcec.PublicKey)(&key2.PublicKey). SerializeCompressed() address2, err := btcutil.NewAddressPubKey(pk2, - btcwire.TestNet3) + &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make address 2 for %s: %v", msg, err) @@ -4555,7 +4556,7 @@ func TestSignTxOutput(t *testing.T) { } scriptAddr, err := btcutil.NewAddressScriptHash( - pkScript, btcwire.TestNet3) + pkScript, &btcnet.TestNet3Params) if err != nil { t.Errorf("failed to make p2sh addr for %s: %v", msg, err) @@ -4571,7 +4572,7 @@ func TestSignTxOutput(t *testing.T) { } sigScript, err := btcscript.SignTxOutput( - btcwire.TestNet3, tx, i, scriptPkScript, + &btcnet.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address1.EncodeAddress(): {key1, true}, }), mkGetScript(map[string][]byte{ @@ -4592,7 +4593,7 @@ func TestSignTxOutput(t *testing.T) { // Sign with the other key and merge sigScript, err = btcscript.SignTxOutput( - btcwire.TestNet3, tx, i, scriptPkScript, + &btcnet.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address1.EncodeAddress(): {key1, true}, address2.EncodeAddress(): {key2, true}, diff --git a/test_coverage.txt b/test_coverage.txt index aa6dc207..b1285dfb 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -90,7 +90,7 @@ github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) github.com/conformal/btcscript/opcode.go parsedOpcode.alwaysIllegal 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) -github.com/conformal/btcscript/script.go @1320:17 100.00% (4/4) +github.com/conformal/btcscript/script.go @1321:17 100.00% (4/4) github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) @@ -171,9 +171,9 @@ github.com/conformal/btcscript/script.go HasCanonicalPushes 71.43% (5/7) github.com/conformal/btcscript/script.go sign 69.23% (18/26) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/10) github.com/conformal/btcscript/script.go CalcMultiSigStats 0.00% (0/8) -github.com/conformal/btcscript/script.go @577:34 0.00% (0/6) -github.com/conformal/btcscript/script.go @565:34 0.00% (0/4) -github.com/conformal/btcscript/script.go @610:34 0.00% (0/3) +github.com/conformal/btcscript/script.go @578:34 0.00% (0/6) +github.com/conformal/btcscript/script.go @566:34 0.00% (0/4) +github.com/conformal/btcscript/script.go @611:34 0.00% (0/3) github.com/conformal/btcscript/log.go UseLogger 0.00% (0/1) github.com/conformal/btcscript/opcode.go opcodeDisabled 0.00% (0/1) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) From a591c7ec03530aa80ebcb63bc1808708eabddc22 Mon Sep 17 00:00:00 2001 From: David Hill Date: Tue, 27 May 2014 13:59:24 -0400 Subject: [PATCH 131/174] Add new ScriptFlag ScriptStrictMultiSig. ScriptStrictMultiSig verifies that the stack item used by CHECKMULTISIG is zero length. --- opcode.go | 7 ++++++- script.go | 8 ++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/opcode.go b/opcode.go index 998fc953..d63860bb 100644 --- a/opcode.go +++ b/opcode.go @@ -1891,11 +1891,16 @@ func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error { } // bug in bitcoind mean we pop one more stack value than should be used. - _, err = s.dstack.PopByteArray() + dummy, err := s.dstack.PopByteArray() if err != nil { return err } + if s.strictMultiSig && len(dummy) != 0 { + return fmt.Errorf("multisig dummy argument is not zero length: %d", + len(dummy)) + } + if len(signatures) == 0 { s.dstack.PushBool(nsig == 0) return nil diff --git a/script.go b/script.go index 945f3b4f..74df6fe7 100644 --- a/script.go +++ b/script.go @@ -207,6 +207,7 @@ type Script struct { numOps int bip16 bool // treat execution as pay-to-script-hash der bool // enforce DER encoding + strictMultiSig bool // verify multisig stack item is zero length savedFirstStack [][]byte // stack from first script for bip16 scripts } @@ -508,6 +509,10 @@ const ( // recognized by creator of the transaction. Performing a canonical // check enforces script signatures use a unique DER format. ScriptCanonicalSignatures + + // ScriptStrictMultiSig defines whether to verify the stack item + // used by CHECKMULTISIG is zero length. + ScriptStrictMultiSig ) // NewScript returns a new script engine for the provided tx and input idx with @@ -550,6 +555,9 @@ func NewScript(scriptSig []byte, scriptPubKey []byte, txidx int, tx *btcwire.Msg if flags&ScriptCanonicalSignatures == ScriptCanonicalSignatures { m.der = true } + if flags&ScriptStrictMultiSig == ScriptStrictMultiSig { + m.strictMultiSig = true + } m.tx = *tx m.txidx = txidx From e560b6d964bf0278df3fce86ec8baf11b6cf73db Mon Sep 17 00:00:00 2001 From: David Hill Date: Tue, 27 May 2014 14:00:47 -0400 Subject: [PATCH 132/174] sync bitcoind test data. --- data/script_invalid.json | 30 ++++++++++- data/script_valid.json | 80 ++++++++++++++++++++++++++- data/tx_invalid.json | 57 ++++++++++++++------ data/tx_valid.json | 114 +++++++++++++++++++++++++++++---------- internal_test.go | 32 +++++++---- test_coverage.txt | 16 +++--- 6 files changed, 267 insertions(+), 62 deletions(-) diff --git a/data/script_invalid.json b/data/script_invalid.json index cbdb1a3f..d623e974 100644 --- a/data/script_invalid.json +++ b/data/script_invalid.json @@ -1,8 +1,18 @@ [ +["", "DEPTH", "Test the test: we should have an empty stack after scriptSig evaluation"], +[" ", "DEPTH", "and multiple spaces should not change that."], +[" ", "DEPTH"], +[" ", "DEPTH"], + ["", ""], ["", "NOP"], +["", "NOP DEPTH"], ["NOP", ""], +["NOP", "DEPTH"], ["NOP","NOP"], +["NOP","NOP DEPTH"], + +["DEPTH", ""], ["0x4c01","0x01 NOP", "PUSHDATA1 with not enough bytes"], ["0x4d0200ff","0x01 NOP", "PUSHDATA2 with not enough bytes"], @@ -324,9 +334,27 @@ ["NOP", "HASH160 1"], ["NOP", "HASH256 1"], +["", +"0 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG", +"202 CHECKMULTISIGS, fails due to 201 op limit"], + +["1", +"0 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY"], + +["", +"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG", +"Fails due to 201 sig op limit"], + +["1", +"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY"], + + + ["NOP 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "Tests for Script.IsPushOnly()"], ["NOP1 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL"], ["0 0x01 0x50", "HASH160 0x14 0xece424a6bb6ddf4db592c0faed60685047a361b1 EQUAL", "OP_RESERVED in P2SH should fail"], -["0 0x01 VER", "HASH160 0x14 0x0f4d7845db968f2a81b530b6f3c1d6246d4c7e01 EQUAL", "OP_VER in P2SH should fail"] +["0 0x01 VER", "HASH160 0x14 0x0f4d7845db968f2a81b530b6f3c1d6246d4c7e01 EQUAL", "OP_VER in P2SH should fail"], + +["0x00", "'00' EQUAL", "Basic OP_0 execution"] ] diff --git a/data/script_valid.json b/data/script_valid.json index 6313e67b..7546a3b1 100644 --- a/data/script_valid.json +++ b/data/script_valid.json @@ -1,4 +1,16 @@ [ +["", "DEPTH 0 EQUAL", "Test the test: we should have an empty stack after scriptSig evaluation"], +[" ", "DEPTH 0 EQUAL", "and multiple spaces should not change that."], +[" ", "DEPTH 0 EQUAL"], +[" ", "DEPTH 0 EQUAL"], +["1 2", "2 EQUALVERIFY 1 EQUAL", "Similarly whitespace around and between symbols"], +["1 2", "2 EQUALVERIFY 1 EQUAL"], +[" 1 2", "2 EQUALVERIFY 1 EQUAL"], +["1 2 ", "2 EQUALVERIFY 1 EQUAL"], +[" 1 2 ", "2 EQUALVERIFY 1 EQUAL"], + +["1", ""], + ["0x01 0x0b", "11 EQUAL", "push 1 byte"], ["0x02 0x417a", "'Az' EQUAL"], ["0x4b 0x417a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a", @@ -415,6 +427,70 @@ ["NOP", "NOP9 1"], ["NOP", "NOP10 1"], +["", "0 0 0 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "CHECKMULTISIG is allowed to have zero keys and/or sigs"], +["", "0 0 0 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 0 1 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "Zero sigs means no sigs are checked"], +["", "0 0 0 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], + +["", "0 0 0 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "CHECKMULTISIG is allowed to have zero keys and/or sigs"], +["", "0 0 0 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 0 1 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "Zero sigs means no sigs are checked"], +["", "0 0 0 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], + +["", "0 0 'a' 'b' 2 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "Test from up to 20 pubkeys, all not checked"], +["", "0 0 'a' 'b' 'c' 3 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 4 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 5 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 6 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 7 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 8 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 9 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 10 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 11 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 12 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 13 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 14 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 15 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 16 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 17 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 18 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 19 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 2 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 3 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 4 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 5 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 6 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 7 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 8 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 9 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 10 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 11 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 12 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 13 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 14 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 15 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 16 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 17 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 18 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 19 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], + +["", +"0 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG", +"nOpCount is incremented by the number of keys evaluated in addition to the usual one op per op. In this case we have zero keys, so we can execute 201 CHECKMULTISIGS"], + +["1", +"0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY"], + +["", +"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG", +"Even though there are no signatures being checked nOpCount is incremented by the number of keys."], + +["1", +"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY"], + ["0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "Very basic P2SH"], ["0x4c 0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL"], @@ -424,5 +500,7 @@ ["0x4c 0x40 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242", "0x4d 0x4000 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 EQUAL", -"Basic PUSHDATA1 signedness check"] +"Basic PUSHDATA1 signedness check"], + +["0x00", "SIZE 0 EQUAL", "Basic OP_0 execution"] ] diff --git a/data/tx_invalid.json b/data/tx_invalid.json index 3d490a6e..89533da0 100644 --- a/data/tx_invalid.json +++ b/data/tx_invalid.json @@ -2,26 +2,26 @@ ["The following are deserialized transactions which are invalid."], ["They are in the form"], ["[[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], -["serializedTransaction, enforceP2SH]"], +["serializedTransaction, verifyFlags]"], ["Objects that are only a single string (like this one) are ignored"], ["0e1b5688cf179cd9f7cbda1fac0090f6e684bbf8cd946660120197c3f3681809 but with extra junk appended to the end of the scriptPubKey"], [[["6ca7ec7b1847f6bdbd737176050e6a08d66ccd55bb94ad24f4018024107a5827", 0, "0x41 0x043b640e983c9690a14c039a2037ecc3467b27a0dcd58f19d76c7bc118d09fec45adc5370a1c5bf8067ca9f5557a4cf885fdb0fe0dcc9c3a7137226106fbc779a5 CHECKSIG VERIFY 1"]], -"010000000127587a10248001f424ad94bb55cd6cd6086a0e05767173bdbdf647187beca76c000000004948304502201b822ad10d6adc1a341ae8835be3f70a25201bbff31f59cbb9c5353a5f0eca18022100ea7b2f7074e9aa9cf70aa8d0ffee13e6b45dddabf1ab961bda378bcdb778fa4701ffffffff0100f2052a010000001976a914fc50c5907d86fed474ba5ce8b12a66e0a4c139d888ac00000000", true], +"010000000127587a10248001f424ad94bb55cd6cd6086a0e05767173bdbdf647187beca76c000000004948304502201b822ad10d6adc1a341ae8835be3f70a25201bbff31f59cbb9c5353a5f0eca18022100ea7b2f7074e9aa9cf70aa8d0ffee13e6b45dddabf1ab961bda378bcdb778fa4701ffffffff0100f2052a010000001976a914fc50c5907d86fed474ba5ce8b12a66e0a4c139d888ac00000000", "P2SH"], ["This is the nearly-standard transaction with CHECKSIGVERIFY 1 instead of CHECKSIG from tx_valid.json"], ["but with the signature duplicated in the scriptPubKey with a non-standard pushdata prefix"], ["See FindAndDelete, which will only remove if it uses the same pushdata prefix as is standard"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x4c 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]], -"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", "P2SH"], ["Same as above, but with the sig in the scriptSig also pushed with the same non-standard OP_PUSHDATA"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x4c 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]], -"01000000010001000000000000000000000000000000000000000000000000000000000000000000006b4c473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006b4c473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", "P2SH"], ["An invalid P2SH Transaction"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]], -"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", true], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", "P2SH"], ["Tests for CheckTransaction()"], ["No inputs"], @@ -29,29 +29,29 @@ ["No outputs"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x05ab9e14d983742513f0f451e105ffb4198d1dd4 EQUAL"]], -"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022100f16703104aab4e4088317c862daec83440242411b039d14280e03dd33b487ab802201318a7be236672c5c56083eb7a5a195bc57a40af7923ff8545016cd3b571e2a601232103c40e5d339df3f30bf753e7e04450ae4ef76c9e45587d1d993bdc4cd06f0651c7acffffffff0000000000", true], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022100f16703104aab4e4088317c862daec83440242411b039d14280e03dd33b487ab802201318a7be236672c5c56083eb7a5a195bc57a40af7923ff8545016cd3b571e2a601232103c40e5d339df3f30bf753e7e04450ae4ef76c9e45587d1d993bdc4cd06f0651c7acffffffff0000000000", "P2SH"], ["Negative output"], -["Removed because btcscript doesn't so tx sanity checking."], +["Removed because btcscript doesn't do tx sanity checking."], ["MAX_MONEY + 1 output"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x32afac281462b822adbec5094b8d4d337dd5bd6a EQUAL"]], -"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010140075af0750700015100000000", true], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010140075af0750700015100000000", "P2SH"], ["MAX_MONEY output + 1 output"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xb558cbf4930954aa6a344363a15668d7477ae716 EQUAL"]], -"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510001000000000000015100000000", true], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510001000000000000015100000000", "P2SH"], ["Duplicate inputs"], ["Removed because btcscript doesn't check input duplication, btcchain does"], ["Coinbase of size 1"], ["Note the input is just required to make the tester happy"], -["Removed because btcscript dooesn't handle coinbase checking, btcchain does"], +["Removed because btcscript doesn't handle coinbase checking, btcchain does"], ["Coinbase of size 101"], ["Note the input is just required to make the tester happy"], -["Removed because btcscript dooesn't handle coinbase checking, btcchain does"], +["Removed because btcscript doesn't handle coinbase checking, btcchain does"], ["Null txin"], ["Removed because btcscript doesn't do tx sanity checking."], @@ -59,16 +59,43 @@ ["Same as the transactions in valid with one input SIGHASH_ALL and one SIGHASH_ANYONECANPAY, but we set the _ANYONECANPAY sequence number, invalidating the SIGHASH_ALL signature"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"], ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]], - "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df10101000000000200000000000000000000000000000000000000000000000000000000000000000000484730440220201dc2d030e380e8f9cfb41b442d930fa5a685bb2c8db5906671f865507d0670022018d9e7a8d4c8d86a73c2a724ee38ef983ec249827e0e464841735955c707ece98101000000010100000000000000015100000000", true], + "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df10101000000000200000000000000000000000000000000000000000000000000000000000000000000484730440220201dc2d030e380e8f9cfb41b442d930fa5a685bb2c8db5906671f865507d0670022018d9e7a8d4c8d86a73c2a724ee38ef983ec249827e0e464841735955c707ece98101000000010100000000000000015100000000", "P2SH"], -["Incorrect signature order"], +["CHECKMULTISIG with incorrect signature order"], ["Note the input is just required to make the tester happy"], [[["b3da01dd4aae683c7aee4d5d8b52a540a508e1115f77cd7fa9a291243f501223", 0, "HASH160 0x14 0xb1ce99298d5f07364b57b1e5c9cc00be0b04a954 EQUAL"]], -"01000000012312503f2491a2a97fcd775f11e108a540a5528b5d4dee7a3c68ae4add01dab300000000fdfe000048304502207aacee820e08b0b174e248abd8d7a34ed63b5da3abedb99934df9fddd65c05c4022100dfe87896ab5ee3df476c2655f9fbe5bd089dccbef3e4ea05b5d121169fe7f5f401483045022100f6649b0eddfdfd4ad55426663385090d51ee86c3481bdc6b0c18ea6c0ece2c0b0220561c315b07cffa6f7dd9df96dbae9200c2dee09bf93cc35ca05e6cdf613340aa014c695221031d11db38972b712a9fe1fc023577c7ae3ddb4a3004187d41c45121eecfdbb5b7210207ec36911b6ad2382860d32989c7b8728e9489d7bbc94a6b5509ef0029be128821024ea9fac06f666a4adc3fc1357b7bec1fd0bdece2b9d08579226a8ebde53058e453aeffffffff0180380100000000001976a914c9b99cddf847d10685a4fabaa0baf505f7c3dfab88ac00000000", true], +"01000000012312503f2491a2a97fcd775f11e108a540a5528b5d4dee7a3c68ae4add01dab300000000fdfe000048304502207aacee820e08b0b174e248abd8d7a34ed63b5da3abedb99934df9fddd65c05c4022100dfe87896ab5ee3df476c2655f9fbe5bd089dccbef3e4ea05b5d121169fe7f5f401483045022100f6649b0eddfdfd4ad55426663385090d51ee86c3481bdc6b0c18ea6c0ece2c0b0220561c315b07cffa6f7dd9df96dbae9200c2dee09bf93cc35ca05e6cdf613340aa014c695221031d11db38972b712a9fe1fc023577c7ae3ddb4a3004187d41c45121eecfdbb5b7210207ec36911b6ad2382860d32989c7b8728e9489d7bbc94a6b5509ef0029be128821024ea9fac06f666a4adc3fc1357b7bec1fd0bdece2b9d08579226a8ebde53058e453aeffffffff0180380100000000001976a914c9b99cddf847d10685a4fabaa0baf505f7c3dfab88ac00000000", "P2SH"], + + +["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], +["It is an OP_CHECKMULTISIG with the dummy value missing"], +[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004847304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"], + + +["CHECKMULTISIG SCRIPT_VERIFY_NULLDUMMY tests:"], + +["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], +["It is an OP_CHECKMULTISIG with the dummy value set to something other than an empty string"], +[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004a010047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"], + +["As above, but using a OP_1"], +[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000495147304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"], + +["As above, but using a OP_1NEGATE"], +[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000494f47304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"], + +["As above, but with the dummy byte missing"], +[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004847304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"], + ["Empty stack when we try to run CHECKSIG"], [[["ad503f72c18df5801ee64d76090afe4c607fb2b822e9b7b63c5826c50e22fc3b", 0, "0x21 0x027c3a97665bf283a102a587a62a30a0c102d4d3b141015e2cae6f64e2543113e5 CHECKSIG NOT"]], -"01000000013bfc220ec526583cb6b7e922b8b27f604cfe0a09764de61e80f58dc1723f50ad0000000000ffffffff0101000000000000002321027c3a97665bf283a102a587a62a30a0c102d4d3b141015e2cae6f64e2543113e5ac00000000", true], +"01000000013bfc220ec526583cb6b7e922b8b27f604cfe0a09764de61e80f58dc1723f50ad0000000000ffffffff0101000000000000002321027c3a97665bf283a102a587a62a30a0c102d4d3b141015e2cae6f64e2543113e5ac00000000", "P2SH"], ["Make diffs cleaner by leaving a comment here without comma at the end"] ] diff --git a/data/tx_valid.json b/data/tx_valid.json index c206f7a7..40275cd1 100644 --- a/data/tx_valid.json +++ b/data/tx_valid.json @@ -2,7 +2,7 @@ ["The following are deserialized transactions which are valid."], ["They are in the form"], ["[[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], -["serializedTransaction, enforceP2SH]"], +["serializedTransaction, verifyFlags]"], ["Objects that are only a single string (like this one) are ignored"], ["The following is 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], @@ -10,113 +10,173 @@ ["See http://r6.ca/blog/20111119T211504Z.html"], ["It is also the first OP_CHECKMULTISIG transaction in standard form"], [[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], -"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000490047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", true], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000490047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"], ["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], -["It has an arbitrary extra byte stuffed into the signature at pos length - 2"], +["It is an OP_CHECKMULTISIG with an arbitrary extra byte stuffed into the signature at pos length - 2"], +["The dummy byte is fine however, so the NULLDUMMY flag should be happy"], [[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], -"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004A0048304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2bab01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", true], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004A0048304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2bab01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"], + +["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], +["It is an OP_CHECKMULTISIG with the dummy value set to something other than an empty string"], +[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004a01ff47304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"], + +["As above, but using a OP_1"], +[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000495147304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"], + +["As above, but using a OP_1NEGATE"], +[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000494f47304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"], ["The following is c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73"], ["It is of interest because it contains a 0-sequence as well as a signature of SIGHASH type 0 (which is not a real type)"], [[["406b2b06bcd34d3c8733e6b79f7a394c8a431fbf4ff5ac705c93f4076bb77602", 0, "DUP HASH160 0x14 0xdc44b1164188067c3a32d4780f5996fa14a4f2d9 EQUALVERIFY CHECKSIG"]], -"01000000010276b76b07f4935c70acf54fbf1f438a4c397a9fb7e633873c4dd3bc062b6b40000000008c493046022100d23459d03ed7e9511a47d13292d3430a04627de6235b6e51a40f9cd386f2abe3022100e7d25b080f0bb8d8d5f878bba7d54ad2fda650ea8d158a33ee3cbd11768191fd004104b0e2c879e4daf7b9ab68350228c159766676a14f5815084ba166432aab46198d4cca98fa3e9981d0a90b2effc514b76279476550ba3663fdcaff94c38420e9d5000000000100093d00000000001976a9149a7b0f3b80c6baaeedce0a0842553800f832ba1f88ac00000000", true], +"01000000010276b76b07f4935c70acf54fbf1f438a4c397a9fb7e633873c4dd3bc062b6b40000000008c493046022100d23459d03ed7e9511a47d13292d3430a04627de6235b6e51a40f9cd386f2abe3022100e7d25b080f0bb8d8d5f878bba7d54ad2fda650ea8d158a33ee3cbd11768191fd004104b0e2c879e4daf7b9ab68350228c159766676a14f5815084ba166432aab46198d4cca98fa3e9981d0a90b2effc514b76279476550ba3663fdcaff94c38420e9d5000000000100093d00000000001976a9149a7b0f3b80c6baaeedce0a0842553800f832ba1f88ac00000000", "P2SH"], ["A nearly-standard transaction with CHECKSIGVERIFY 1 instead of CHECKSIG"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1"]], -"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", "P2SH"], ["Same as above, but with the signature duplicated in the scriptPubKey with the proper pushdata prefix"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]], -"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", "P2SH"], ["The following is f7fdd091fa6d8f5e7a8c2458f5c38faffff2d3f1406b6e4fe2c99dcc0d2d1cbb"], ["It caught a bug in the workaround for 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63 in an overly simple implementation"], [[["b464e85df2a238416f8bdae11d120add610380ea07f4ef19c5f9dfd472f96c3d", 0, "DUP HASH160 0x14 0xbef80ecf3a44500fda1bc92176e442891662aed2 EQUALVERIFY CHECKSIG"], ["b7978cc96e59a8b13e0865d3f95657561a7f725be952438637475920bac9eb21", 1, "DUP HASH160 0x14 0xbef80ecf3a44500fda1bc92176e442891662aed2 EQUALVERIFY CHECKSIG"]], -"01000000023d6cf972d4dff9c519eff407ea800361dd0a121de1da8b6f4138a2f25de864b4000000008a4730440220ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e022049cffa1cdc102a0b56e0e04913606c70af702a1149dc3b305ab9439288fee090014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff21ebc9ba20594737864352e95b727f1a565756f9d365083eb1a8596ec98c97b7010000008a4730440220503ff10e9f1e0de731407a4a245531c9ff17676eda461f8ceeb8c06049fa2c810220c008ac34694510298fa60b3f000df01caa244f165b727d4896eb84f81e46bcc4014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff01f0da5200000000001976a914857ccd42dded6df32949d4646dfa10a92458cfaa88ac00000000", true], +"01000000023d6cf972d4dff9c519eff407ea800361dd0a121de1da8b6f4138a2f25de864b4000000008a4730440220ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e022049cffa1cdc102a0b56e0e04913606c70af702a1149dc3b305ab9439288fee090014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff21ebc9ba20594737864352e95b727f1a565756f9d365083eb1a8596ec98c97b7010000008a4730440220503ff10e9f1e0de731407a4a245531c9ff17676eda461f8ceeb8c06049fa2c810220c008ac34694510298fa60b3f000df01caa244f165b727d4896eb84f81e46bcc4014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff01f0da5200000000001976a914857ccd42dded6df32949d4646dfa10a92458cfaa88ac00000000", "P2SH"], ["The following tests for the presence of a bug in the handling of SIGHASH_SINGLE"], ["It results in signing the constant 1, instead of something generated based on the transaction,"], ["when the input doing the signing has an index greater than the maximum output index"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0xe52b482f2faa8ecbf0db344f93c84ac908557f33 EQUALVERIFY CHECKSIG"], ["0000000000000000000000000000000000000000000000000000000000000200", 0, "1"]], -"01000000020002000000000000000000000000000000000000000000000000000000000000000000000151ffffffff0001000000000000000000000000000000000000000000000000000000000000000000006b483045022100c9cdd08798a28af9d1baf44a6c77bcc7e279f47dc487c8c899911bc48feaffcc0220503c5c50ae3998a733263c5c0f7061b483e2b56c4c41b456e7d2f5a78a74c077032102d5c25adb51b61339d2b05315791e21bbe80ea470a49db0135720983c905aace0ffffffff010000000000000000015100000000", true], +"01000000020002000000000000000000000000000000000000000000000000000000000000000000000151ffffffff0001000000000000000000000000000000000000000000000000000000000000000000006b483045022100c9cdd08798a28af9d1baf44a6c77bcc7e279f47dc487c8c899911bc48feaffcc0220503c5c50ae3998a733263c5c0f7061b483e2b56c4c41b456e7d2f5a78a74c077032102d5c25adb51b61339d2b05315791e21bbe80ea470a49db0135720983c905aace0ffffffff010000000000000000015100000000", "P2SH"], ["An invalid P2SH Transaction"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]], -"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", false], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", "NONE"], ["A valid P2SH Transaction using the standard transaction type put forth in BIP 16"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x8febbed40483661de6958d957412f82deed8e2f7 EQUAL"]], -"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100c66c9cdf4c43609586d15424c54707156e316d88b0a1534c9e6b0d4f311406310221009c0fe51dbc9c4ab7cc25d3fdbeccf6679fe6827f08edf2b4a9f16ee3eb0e438a0123210338e8034509af564c62644c07691942e0c056752008a173c89f60ab2a88ac2ebfacffffffff010000000000000000015100000000", true], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100c66c9cdf4c43609586d15424c54707156e316d88b0a1534c9e6b0d4f311406310221009c0fe51dbc9c4ab7cc25d3fdbeccf6679fe6827f08edf2b4a9f16ee3eb0e438a0123210338e8034509af564c62644c07691942e0c056752008a173c89f60ab2a88ac2ebfacffffffff010000000000000000015100000000", "P2SH"], ["Tests for CheckTransaction()"], ["MAX_MONEY output"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x32afac281462b822adbec5094b8d4d337dd5bd6a EQUAL"]], -"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010040075af0750700015100000000", true], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010040075af0750700015100000000", "P2SH"], ["MAX_MONEY output + 0 output"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xb558cbf4930954aa6a344363a15668d7477ae716 EQUAL"]], -"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510000000000000000015100000000", true], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510000000000000000015100000000", "P2SH"], ["Coinbase of size 2"], ["Note the input is just required to make the tester happy"], [[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]], -"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff025151ffffffff010000000000000000015100000000", true], +"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff025151ffffffff010000000000000000015100000000", "P2SH"], ["Coinbase of size 100"], ["Note the input is just required to make the tester happy"], [[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]], -"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6451515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151ffffffff010000000000000000015100000000", true], +"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6451515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151ffffffff010000000000000000015100000000", "P2SH"], ["Simple transaction with first input is signed with SIGHASH_ALL, second with SIGHASH_ANYONECANPAY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"], ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]], - "010000000200010000000000000000000000000000000000000000000000000000000000000000000049483045022100d180fd2eb9140aeb4210c9204d3f358766eb53842b2a9473db687fa24b12a3cc022079781799cd4f038b85135bbe49ec2b57f306b2bb17101b17f71f000fcab2b6fb01ffffffff0002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", true], + "010000000200010000000000000000000000000000000000000000000000000000000000000000000049483045022100d180fd2eb9140aeb4210c9204d3f358766eb53842b2a9473db687fa24b12a3cc022079781799cd4f038b85135bbe49ec2b57f306b2bb17101b17f71f000fcab2b6fb01ffffffff0002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", "P2SH"], ["Same as above, but we change the sequence number of the first input to check that SIGHASH_ANYONECANPAY is being followed"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"], ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]], - "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df101010000000002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", true], + "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df101010000000002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", "P2SH"], ["afd9c17f8913577ec3509520bd6e5d63e9c0fd2a5f70c787993b097ba6ca9fae which has several SIGHASH_SINGLE signatures"], [[["63cfa5a09dc540bf63e53713b82d9ea3692ca97cd608c384f2aa88e51a0aac70", 0, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"], ["04e8d0fcf3846c6734477b98f0f3d4badfb78f020ee097a0be5fe347645b817d", 1, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"], ["ee1377aff5d0579909e11782e1d2f5f7b84d26537be7f5516dd4e43373091f3f", 1, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"]], - "010000000370ac0a1ae588aaf284c308d67ca92c69a39e2db81337e563bf40c59da0a5cf63000000006a4730440220360d20baff382059040ba9be98947fd678fb08aab2bb0c172efa996fd8ece9b702201b4fb0de67f015c90e7ac8a193aeab486a1f587e0f54d0fb9552ef7f5ce6caec032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff7d815b6447e35fbea097e00e028fb7dfbad4f3f0987b4734676c84f3fcd0e804010000006b483045022100c714310be1e3a9ff1c5f7cacc65c2d8e781fc3a88ceb063c6153bf950650802102200b2d0979c76e12bb480da635f192cc8dc6f905380dd4ac1ff35a4f68f462fffd032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff3f1f097333e4d46d51f5e77b53264db8f7f5d2e18217e1099957d0f5af7713ee010000006c493046022100b663499ef73273a3788dea342717c2640ac43c5a1cf862c9e09b206fcb3f6bb8022100b09972e75972d9148f2bdd462e5cb69b57c1214b88fc55ca638676c07cfc10d8032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff0380841e00000000001976a914bfb282c70c4191f45b5a6665cad1682f2c9cfdfb88ac80841e00000000001976a9149857cc07bed33a5cf12b9c5e0500b675d500c81188ace0fd1c00000000001976a91443c52850606c872403c0601e69fa34b26f62db4a88ac00000000", true], + "010000000370ac0a1ae588aaf284c308d67ca92c69a39e2db81337e563bf40c59da0a5cf63000000006a4730440220360d20baff382059040ba9be98947fd678fb08aab2bb0c172efa996fd8ece9b702201b4fb0de67f015c90e7ac8a193aeab486a1f587e0f54d0fb9552ef7f5ce6caec032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff7d815b6447e35fbea097e00e028fb7dfbad4f3f0987b4734676c84f3fcd0e804010000006b483045022100c714310be1e3a9ff1c5f7cacc65c2d8e781fc3a88ceb063c6153bf950650802102200b2d0979c76e12bb480da635f192cc8dc6f905380dd4ac1ff35a4f68f462fffd032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff3f1f097333e4d46d51f5e77b53264db8f7f5d2e18217e1099957d0f5af7713ee010000006c493046022100b663499ef73273a3788dea342717c2640ac43c5a1cf862c9e09b206fcb3f6bb8022100b09972e75972d9148f2bdd462e5cb69b57c1214b88fc55ca638676c07cfc10d8032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff0380841e00000000001976a914bfb282c70c4191f45b5a6665cad1682f2c9cfdfb88ac80841e00000000001976a9149857cc07bed33a5cf12b9c5e0500b675d500c81188ace0fd1c00000000001976a91443c52850606c872403c0601e69fa34b26f62db4a88ac00000000", "P2SH"], ["ddc454a1c0c35c188c98976b17670f69e586d9c0f3593ea879928332f0a069e7, which spends an input that pushes using a PUSHDATA1 that is negative when read as signed"], [[["c5510a5dd97a25f43175af1fe649b707b1df8e1a41489bac33a23087027a2f48", 0, "0x4c 0xae 0x606563686f2022553246736447566b58312b5a536e587574356542793066794778625456415675534a6c376a6a334878416945325364667657734f53474f36633338584d7439435c6e543249584967306a486956304f376e775236644546673d3d22203e20743b206f70656e73736c20656e63202d7061737320706173733a5b314a564d7751432d707269766b65792d6865785d202d64202d6165732d3235362d636263202d61202d696e207460 DROP DUP HASH160 0x14 0xbfd7436b6265aa9de506f8a994f881ff08cc2872 EQUALVERIFY CHECKSIG"]], - "0100000001482f7a028730a233ac9b48411a8edfb107b749e61faf7531f4257ad95d0a51c5000000008b483045022100bf0bbae9bde51ad2b222e87fbf67530fbafc25c903519a1e5dcc52a32ff5844e022028c4d9ad49b006dd59974372a54291d5764be541574bb0c4dc208ec51f80b7190141049dd4aad62741dc27d5f267f7b70682eee22e7e9c1923b9c0957bdae0b96374569b460eb8d5b40d972e8c7c0ad441de3d94c4a29864b212d56050acb980b72b2bffffffff0180969800000000001976a914e336d0017a9d28de99d16472f6ca6d5a3a8ebc9988ac00000000", true], + "0100000001482f7a028730a233ac9b48411a8edfb107b749e61faf7531f4257ad95d0a51c5000000008b483045022100bf0bbae9bde51ad2b222e87fbf67530fbafc25c903519a1e5dcc52a32ff5844e022028c4d9ad49b006dd59974372a54291d5764be541574bb0c4dc208ec51f80b7190141049dd4aad62741dc27d5f267f7b70682eee22e7e9c1923b9c0957bdae0b96374569b460eb8d5b40d972e8c7c0ad441de3d94c4a29864b212d56050acb980b72b2bffffffff0180969800000000001976a914e336d0017a9d28de99d16472f6ca6d5a3a8ebc9988ac00000000", "P2SH"], ["Correct signature order"], ["Note the input is just required to make the tester happy"], [[["b3da01dd4aae683c7aee4d5d8b52a540a508e1115f77cd7fa9a291243f501223", 0, "HASH160 0x14 0xb1ce99298d5f07364b57b1e5c9cc00be0b04a954 EQUAL"]], -"01000000012312503f2491a2a97fcd775f11e108a540a5528b5d4dee7a3c68ae4add01dab300000000fdfe0000483045022100f6649b0eddfdfd4ad55426663385090d51ee86c3481bdc6b0c18ea6c0ece2c0b0220561c315b07cffa6f7dd9df96dbae9200c2dee09bf93cc35ca05e6cdf613340aa0148304502207aacee820e08b0b174e248abd8d7a34ed63b5da3abedb99934df9fddd65c05c4022100dfe87896ab5ee3df476c2655f9fbe5bd089dccbef3e4ea05b5d121169fe7f5f4014c695221031d11db38972b712a9fe1fc023577c7ae3ddb4a3004187d41c45121eecfdbb5b7210207ec36911b6ad2382860d32989c7b8728e9489d7bbc94a6b5509ef0029be128821024ea9fac06f666a4adc3fc1357b7bec1fd0bdece2b9d08579226a8ebde53058e453aeffffffff0180380100000000001976a914c9b99cddf847d10685a4fabaa0baf505f7c3dfab88ac00000000", true], +"01000000012312503f2491a2a97fcd775f11e108a540a5528b5d4dee7a3c68ae4add01dab300000000fdfe0000483045022100f6649b0eddfdfd4ad55426663385090d51ee86c3481bdc6b0c18ea6c0ece2c0b0220561c315b07cffa6f7dd9df96dbae9200c2dee09bf93cc35ca05e6cdf613340aa0148304502207aacee820e08b0b174e248abd8d7a34ed63b5da3abedb99934df9fddd65c05c4022100dfe87896ab5ee3df476c2655f9fbe5bd089dccbef3e4ea05b5d121169fe7f5f4014c695221031d11db38972b712a9fe1fc023577c7ae3ddb4a3004187d41c45121eecfdbb5b7210207ec36911b6ad2382860d32989c7b8728e9489d7bbc94a6b5509ef0029be128821024ea9fac06f666a4adc3fc1357b7bec1fd0bdece2b9d08579226a8ebde53058e453aeffffffff0180380100000000001976a914c9b99cddf847d10685a4fabaa0baf505f7c3dfab88ac00000000", "P2SH"], ["cc60b1f899ec0a69b7c3f25ddf32c4524096a9c5b01cbd84c6d0312a0c478984, which is a fairly strange transaction which relies on OP_CHECKSIG returning 0 when checking a completely invalid sig of length 0"], [[["cbebc4da731e8995fe97f6fadcd731b36ad40e5ecb31e38e904f6e5982fa09f7", 0, "0x2102085c6600657566acc2d6382a47bc3f324008d2aa10940dd7705a48aa2a5a5e33ac7c2103f5d0fb955f95dd6be6115ce85661db412ec6a08abcbfce7da0ba8297c6cc0ec4ac7c5379a820d68df9e32a147cffa36193c6f7c43a1c8c69cda530e1c6db354bfabdcfefaf3c875379a820f531f3041d3136701ea09067c53e7159c8f9b2746a56c3d82966c54bbc553226879a5479827701200122a59a5379827701200122a59a6353798277537982778779679a68"]], -"0100000001f709fa82596e4f908ee331cb5e0ed46ab331d7dcfaf697fe95891e73dac4ebcb000000008c20ca42095840735e89283fec298e62ac2ddea9b5f34a8cbb7097ad965b87568100201b1b01dc829177da4a14551d2fc96a9db00c6501edfa12f22cd9cefd335c227f483045022100a9df60536df5733dd0de6bc921fab0b3eee6426501b43a228afa2c90072eb5ca02201c78b74266fac7d1db5deff080d8a403743203f109fbcabf6d5a760bf87386d20100ffffffff01c075790000000000232103611f9a45c18f28f06f19076ad571c344c82ce8fcfe34464cf8085217a2d294a6ac00000000", true], +"0100000001f709fa82596e4f908ee331cb5e0ed46ab331d7dcfaf697fe95891e73dac4ebcb000000008c20ca42095840735e89283fec298e62ac2ddea9b5f34a8cbb7097ad965b87568100201b1b01dc829177da4a14551d2fc96a9db00c6501edfa12f22cd9cefd335c227f483045022100a9df60536df5733dd0de6bc921fab0b3eee6426501b43a228afa2c90072eb5ca02201c78b74266fac7d1db5deff080d8a403743203f109fbcabf6d5a760bf87386d20100ffffffff01c075790000000000232103611f9a45c18f28f06f19076ad571c344c82ce8fcfe34464cf8085217a2d294a6ac00000000", "P2SH"], ["Empty pubkey"], [[["229257c295e7f555421c1bfec8538dd30a4b5c37c1c8810bbe83cafa7811652c", 0, "0x00 CHECKSIG NOT"]], -"01000000012c651178faca83be0b81c8c1375c4b0ad38d53c8fe1b1c4255f5e795c25792220000000049483045022100d6044562284ac76c985018fc4a90127847708c9edb280996c507b28babdc4b2a02203d74eca3f1a4d1eea7ff77b528fde6d5dc324ec2dbfdb964ba885f643b9704cd01ffffffff010100000000000000232102c2410f8891ae918cab4ffc4bb4a3b0881be67c7a1e7faa8b5acf9ab8932ec30cac00000000", true], +"01000000012c651178faca83be0b81c8c1375c4b0ad38d53c8fe1b1c4255f5e795c25792220000000049483045022100d6044562284ac76c985018fc4a90127847708c9edb280996c507b28babdc4b2a02203d74eca3f1a4d1eea7ff77b528fde6d5dc324ec2dbfdb964ba885f643b9704cd01ffffffff010100000000000000232102c2410f8891ae918cab4ffc4bb4a3b0881be67c7a1e7faa8b5acf9ab8932ec30cac00000000", "P2SH"], ["Empty signature"], [[["9ca93cfd8e3806b9d9e2ba1cf64e3cc6946ee0119670b1796a09928d14ea25f7", 0, "0x21 0x028a1d66975dbdf97897e3a4aef450ebeb5b5293e4a0b4a6d3a2daaa0b2b110e02 CHECKSIG NOT"]], -"0100000001f725ea148d92096a79b1709611e06e94c63c4ef61cbae2d9b906388efd3ca99c000000000100ffffffff0101000000000000002321028a1d66975dbdf97897e3a4aef450ebeb5b5293e4a0b4a6d3a2daaa0b2b110e02ac00000000", true], +"0100000001f725ea148d92096a79b1709611e06e94c63c4ef61cbae2d9b906388efd3ca99c000000000100ffffffff0101000000000000002321028a1d66975dbdf97897e3a4aef450ebeb5b5293e4a0b4a6d3a2daaa0b2b110e02ac00000000", "P2SH"], [[["444e00ed7840d41f20ecd9c11d3f91982326c731a02f3c05748414a4fa9e59be", 0, "1 0x00 0x21 0x02136b04758b0b6e363e7a6fbe83aaf527a153db2b060d36cc29f7f8309ba6e458 2 CHECKMULTISIG"]], -"0100000001be599efaa4148474053c2fa031c7262398913f1dc1d9ec201fd44078ed004e44000000004900473044022022b29706cb2ed9ef0cb3c97b72677ca2dfd7b4160f7b4beb3ba806aa856c401502202d1e52582412eba2ed474f1f437a427640306fd3838725fab173ade7fe4eae4a01ffffffff010100000000000000232103ac4bba7e7ca3e873eea49e08132ad30c7f03640b6539e9b59903cf14fd016bbbac00000000", true], +"0100000001be599efaa4148474053c2fa031c7262398913f1dc1d9ec201fd44078ed004e44000000004900473044022022b29706cb2ed9ef0cb3c97b72677ca2dfd7b4160f7b4beb3ba806aa856c401502202d1e52582412eba2ed474f1f437a427640306fd3838725fab173ade7fe4eae4a01ffffffff010100000000000000232103ac4bba7e7ca3e873eea49e08132ad30c7f03640b6539e9b59903cf14fd016bbbac00000000", "P2SH"], [[["e16abbe80bf30c080f63830c8dbf669deaef08957446e95940227d8c5e6db612", 0, "1 0x21 0x03905380c7013e36e6e19d305311c1b81fce6581f5ee1c86ef0627c68c9362fc9f 0x00 2 CHECKMULTISIG"]], -"010000000112b66d5e8c7d224059e946749508efea9d66bf8d0c83630f080cf30be8bb6ae100000000490047304402206ffe3f14caf38ad5c1544428e99da76ffa5455675ec8d9780fac215ca17953520220779502985e194d84baa36b9bd40a0dbd981163fa191eb884ae83fc5bd1c86b1101ffffffff010100000000000000232103905380c7013e36e6e19d305311c1b81fce6581f5ee1c86ef0627c68c9362fc9fac00000000", true], +"010000000112b66d5e8c7d224059e946749508efea9d66bf8d0c83630f080cf30be8bb6ae100000000490047304402206ffe3f14caf38ad5c1544428e99da76ffa5455675ec8d9780fac215ca17953520220779502985e194d84baa36b9bd40a0dbd981163fa191eb884ae83fc5bd1c86b1101ffffffff010100000000000000232103905380c7013e36e6e19d305311c1b81fce6581f5ee1c86ef0627c68c9362fc9fac00000000", "P2SH"], [[["ebbcf4bfce13292bd791d6a65a2a858d59adbf737e387e40370d4e64cc70efb0", 0, "2 0x21 0x033bcaa0a602f0d44cc9d5637c6e515b0471db514c020883830b7cefd73af04194 0x21 0x03a88b326f8767f4f192ce252afe33c94d25ab1d24f27f159b3cb3aa691ffe1423 2 CHECKMULTISIG NOT"]], -"0100000001b0ef70cc644e0d37407e387e73bfad598d852a5aa6d691d72b2913cebff4bceb000000004a00473044022068cd4851fc7f9a892ab910df7a24e616f293bcb5c5fbdfbc304a194b26b60fba022078e6da13d8cb881a22939b952c24f88b97afd06b4c47a47d7f804c9a352a6d6d0100ffffffff0101000000000000002321033bcaa0a602f0d44cc9d5637c6e515b0471db514c020883830b7cefd73af04194ac00000000", true], +"0100000001b0ef70cc644e0d37407e387e73bfad598d852a5aa6d691d72b2913cebff4bceb000000004a00473044022068cd4851fc7f9a892ab910df7a24e616f293bcb5c5fbdfbc304a194b26b60fba022078e6da13d8cb881a22939b952c24f88b97afd06b4c47a47d7f804c9a352a6d6d0100ffffffff0101000000000000002321033bcaa0a602f0d44cc9d5637c6e515b0471db514c020883830b7cefd73af04194ac00000000", "P2SH"], [[["ba4cd7ae2ad4d4d13ebfc8ab1d93a63e4a6563f25089a18bf0fc68f282aa88c1", 0, "2 0x21 0x037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1 0x21 0x02edc823cd634f2c4033d94f5755207cb6b60c4b1f1f056ad7471c47de5f2e4d50 2 CHECKMULTISIG NOT"]], -"0100000001c188aa82f268fcf08ba18950f263654a3ea6931dabc8bf3ed1d4d42aaed74cba000000004b0000483045022100940378576e069aca261a6b26fb38344e4497ca6751bb10905c76bb689f4222b002204833806b014c26fd801727b792b1260003c55710f87c5adbd7a9cb57446dbc9801ffffffff0101000000000000002321037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1ac00000000", true], +"0100000001c188aa82f268fcf08ba18950f263654a3ea6931dabc8bf3ed1d4d42aaed74cba000000004b0000483045022100940378576e069aca261a6b26fb38344e4497ca6751bb10905c76bb689f4222b002204833806b014c26fd801727b792b1260003c55710f87c5adbd7a9cb57446dbc9801ffffffff0101000000000000002321037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1ac00000000", "P2SH"], + + +["OP_CODESEPARATOR tests"], + +["Test that SignatureHash() removes OP_CODESEPARATOR with FindAndDelete()"], +[[["bc7fd132fcf817918334822ee6d9bd95c889099c96e07ca2c1eb2cc70db63224", 0, "CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIG"]], +"01000000012432b60dc72cebc1a27ce0969c0989c895bdd9e62e8234839117f8fc32d17fbc000000004a493046022100a576b52051962c25e642c0fd3d77ee6c92487048e5d90818bcf5b51abaccd7900221008204f8fb121be4ec3b24483b1f92d89b1b0548513a134e345c5442e86e8617a501ffffffff010000000000000000016a00000000", "P2SH"], +[[["83e194f90b6ef21fa2e3a365b63794fb5daa844bdc9b25de30899fcfe7b01047", 0, "CODESEPARATOR CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIG"]], +"01000000014710b0e7cf9f8930de259bdc4b84aa5dfb9437b665a3e3a21ff26e0bf994e183000000004a493046022100a166121a61b4eeb19d8f922b978ff6ab58ead8a5a5552bf9be73dc9c156873ea02210092ad9bc43ee647da4f6652c320800debcf08ec20a094a0aaf085f63ecb37a17201ffffffff010000000000000000016a00000000", "P2SH"], + +["Hashed data starts at the CODESEPARATOR"], +[[["326882a7f22b5191f1a0cc9962ca4b878cd969cf3b3a70887aece4d801a0ba5e", 0, "0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CODESEPARATOR CHECKSIG"]], +"01000000015ebaa001d8e4ec7a88703a3bcf69d98c874bca6299cca0f191512bf2a7826832000000004948304502203bf754d1c6732fbf87c5dcd81258aefd30f2060d7bd8ac4a5696f7927091dad1022100f5bcb726c4cf5ed0ed34cc13dadeedf628ae1045b7cb34421bc60b89f4cecae701ffffffff010000000000000000016a00000000", "P2SH"], + +["But only if execution has reached it"], +[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIGVERIFY CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIGVERIFY CODESEPARATOR 1"]], +"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a900000000924830450221009c0a27f886a1d8cb87f6f595fbc3163d28f7a81ec3c4b252ee7f3ac77fd13ffa02203caa8dfa09713c8c4d7ef575c75ed97812072405d932bd11e6a1593a98b679370148304502201e3861ef39a526406bad1e20ecad06be7375ad40ddb582c9be42d26c3a0d7b240221009d0a3985e96522e59635d19cc4448547477396ce0ef17a58e7d74c3ef464292301ffffffff010000000000000000016a00000000", "P2SH"], + +["CHECKSIG is legal in scriptSigs"], +[[["ccf7f4053a02e653c36ac75c891b7496d0dc5ce5214f6c913d9cf8f1329ebee0", 0, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]], +"0100000001e0be9e32f1f89c3d916c4f21e55cdcd096741b895cc76ac353e6023a05f4f7cc00000000d86149304602210086e5f736a2c3622ebb62bd9d93d8e5d76508b98be922b97160edc3dcca6d8c47022100b23c312ac232a4473f19d2aeb95ab7bdf2b65518911a0d72d50e38b5dd31dc820121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac4730440220508fa761865c8abd81244a168392876ee1d94e8ed83897066b5e2df2400dad24022043f5ee7538e87e9c6aef7ef55133d3e51da7cc522830a9c4d736977a76ef755c0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"], + +["Same semantics for OP_CODESEPARATOR"], +[[["10c9f0effe83e97f80f067de2b11c6a00c3088a4bce42c5ae761519af9306f3c", 1, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]], +"01000000013c6f30f99a5161e75a2ce4bca488300ca0c6112bde67f0807fe983feeff0c91001000000e608646561646265656675ab61493046022100ce18d384221a731c993939015e3d1bcebafb16e8c0b5b5d14097ec8177ae6f28022100bcab227af90bab33c3fe0a9abfee03ba976ee25dc6ce542526e9b2e56e14b7f10121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac493046022100c3b93edcc0fd6250eb32f2dd8a0bba1754b0f6c3be8ed4100ed582f3db73eba2022100bf75b5bd2eff4d6bf2bda2e34a40fcc07d4aa3cf862ceaa77b47b81eff829f9a01ab21038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"], + +["Signatures are removed from the script they are in by FindAndDelete() in the CHECKSIG code; even multiple instances of one signature can be removed."], +[[["6056ebd549003b10cbbd915cea0d82209fe40b8617104be917a26fa92cbe3d6f", 0, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]], +"01000000016f3dbe2ca96fa217e94b1017860be49f20820dea5c91bdcb103b0049d5eb566000000000fd1d0147304402203989ac8f9ad36b5d0919d97fa0a7f70c5272abee3b14477dc646288a8b976df5022027d19da84a066af9053ad3d1d7459d171b7e3a80bc6c4ef7a330677a6be548140147304402203989ac8f9ad36b5d0919d97fa0a7f70c5272abee3b14477dc646288a8b976df5022027d19da84a066af9053ad3d1d7459d171b7e3a80bc6c4ef7a330677a6be548140121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac47304402203757e937ba807e4a5da8534c17f9d121176056406a6465054bdd260457515c1a02200f02eccf1bec0f3a0d65df37889143c2e88ab7acec61a7b6f5aa264139141a2b0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"], + +["That also includes ahead of the opcode being executed."], +[[["5a6b0021a6042a686b6b94abc36b387bef9109847774e8b1e51eb8cc55c53921", 1, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]], +"01000000012139c555ccb81ee5b1e87477840991ef7b386bc3ab946b6b682a04a621006b5a01000000fdb40148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f2204148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390175ac4830450220646b72c35beeec51f4d5bc1cbae01863825750d7f490864af354e6ea4f625e9c022100f04b98432df3a9641719dbced53393022e7249fb59db993af1118539830aab870148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a580039017521038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"], + +["Finally CHECKMULTISIG removes all signatures prior to hashing the script containing those signatures. In conjunction with the SIGHASH_SINGLE bug this lets us test whether or not FindAndDelete() is actually present in scriptPubKey/redeemScript evaluation by including a signature of the digest 0x01 We can compute in advance for our pubkey, embed it it in the scriptPubKey, and then also using a normal SIGHASH_ALL signature. If FindAndDelete() wasn't run, the 'bugged' signature would still be in the hashed script, and the normal signature would fail."], + +["Here's an example on mainnet within a P2SH redeemScript. Remarkably it's a standard transaction in <0.9"], +[[["b5b598de91787439afd5938116654e0b16b7a0d0f82742ba37564219c5afcbf9", 0, "DUP HASH160 0x14 0xf6f365c40f0739b61de827a44751e5e99032ed8f EQUALVERIFY CHECKSIG"], + ["ab9805c6d57d7070d9a42c5176e47bb705023e6b67249fb6760880548298e742", 0, "HASH160 0x14 0xd8dacdadb7462ae15cd906f1878706d0da8660e6 EQUAL"]], +"0100000002f9cbafc519425637ba4227f8d0a0b7160b4e65168193d5af39747891de98b5b5000000006b4830450221008dd619c563e527c47d9bd53534a770b102e40faa87f61433580e04e271ef2f960220029886434e18122b53d5decd25f1f4acb2480659fea20aabd856987ba3c3907e0121022b78b756e2258af13779c1a1f37ea6800259716ca4b7f0b87610e0bf3ab52a01ffffffff42e7988254800876b69f24676b3e0205b77be476512ca4d970707dd5c60598ab00000000fd260100483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a53034930460221008431bdfa72bc67f9d41fe72e94c88fb8f359ffa30b33c72c121c5a877d922e1002210089ef5fc22dd8bfc6bf9ffdb01a9862d27687d424d1fefbab9e9c7176844a187a014c9052483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c7153aeffffffff01a08601000000000017a914d8dacdadb7462ae15cd906f1878706d0da8660e68700000000", "P2SH"], + +["Same idea, but with bare CHECKMULTISIG"], +[[["ceafe58e0f6e7d67c0409fbbf673c84c166e3c5d3c24af58f7175b18df3bb3db", 0, "DUP HASH160 0x14 0xf6f365c40f0739b61de827a44751e5e99032ed8f EQUALVERIFY CHECKSIG"], + ["ceafe58e0f6e7d67c0409fbbf673c84c166e3c5d3c24af58f7175b18df3bb3db", 1, "2 0x48 0x3045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 3 CHECKMULTISIG"]], +"0100000002dbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce000000006b4830450221009627444320dc5ef8d7f68f35010b4c050a6ed0d96b67a84db99fda9c9de58b1e02203e4b4aaa019e012e65d69b487fdf8719df72f488fa91506a80c49a33929f1fd50121022b78b756e2258af13779c1a1f37ea6800259716ca4b7f0b87610e0bf3ab52a01ffffffffdbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce010000009300483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303ffffffff01a0860100000000001976a9149bc0bbdd3024da4d0c38ed1aecf5c68dd1d3fa1288ac00000000", "P2SH"], + ["Make diffs cleaner by leaving a comment here without comma at the end"] ] diff --git a/internal_test.go b/internal_test.go index 7b86d1be..66592235 100644 --- a/internal_test.go +++ b/internal_test.go @@ -3913,7 +3913,7 @@ func TestBitcoindTxValidTests(t *testing.T) { // for ma is eaitehr a ["this is a comment "] // or [[[previous hash, previous index, previous scripbPubKey]...,] - // serializedTransaction, enforceP2SH] + // serializedTransaction, verifyFlags] testloop: for i, test := range tests { inputs, ok := test[0].([]interface{}) @@ -3945,15 +3945,21 @@ testloop: continue } - enforceP2SH, ok := test[2].(bool) + verifyFlags, ok := test[2].(string) if !ok { - t.Errorf("bad test (arg 3 not bool) %d: %v", i, test) + t.Errorf("bad test (arg 3 not string) %d: %v", i, test) continue } var flags ScriptFlags - if enforceP2SH { - flags |= ScriptBip16 + vFlags := strings.Split(verifyFlags, ",") + for _, flag := range vFlags { + switch flag { + case "P2SH": + flags |= ScriptBip16 + case "NULLDUMMY": + flags |= ScriptStrictMultiSig + } } prevOuts := make(map[btcwire.OutPoint][]byte) @@ -4053,7 +4059,7 @@ func TestBitcoindTxInvalidTests(t *testing.T) { // for ma is eaitehr a ["this is a comment "] // or [[[previous hash, previous index, previous scripbPubKey]...,] - // serializedTransaction, enforceP2SH] + // serializedTransaction, verifyFlags] testloop: for i, test := range tests { inputs, ok := test[0].([]interface{}) @@ -4085,15 +4091,21 @@ testloop: continue } - enforceP2SH, ok := test[2].(bool) + verifyFlags, ok := test[2].(string) if !ok { - t.Errorf("bad test (arg 3 not bool) %d: %v", i, test) + t.Errorf("bad test (arg 3 not string) %d: %v", i, test) continue } var flags ScriptFlags - if enforceP2SH { - flags |= ScriptBip16 + vFlags := strings.Split(verifyFlags, ",") + for _, flag := range vFlags { + switch flag { + case "P2SH": + flags |= ScriptBip16 + case "NULLDUMMY": + flags |= ScriptStrictMultiSig + } } prevOuts := make(map[btcwire.OutPoint][]byte) diff --git a/test_coverage.txt b/test_coverage.txt index b1285dfb..d9638982 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -1,12 +1,12 @@ -github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 100.00% (60/60) +github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 100.00% (62/62) github.com/conformal/btcscript/script.go calcScriptHash 100.00% (39/39) github.com/conformal/btcscript/script.go Script.Step 100.00% (37/37) -github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (29/29) github.com/conformal/btcscript/opcode.go opcodeCheckSig 100.00% (29/29) +github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (29/29) github.com/conformal/btcscript/address.go ExtractPkScriptAddrs 100.00% (27/27) +github.com/conformal/btcscript/script.go NewScript 100.00% (25/25) github.com/conformal/btcscript/script.go CalcScriptInfo 100.00% (25/25) -github.com/conformal/btcscript/script.go NewScript 100.00% (23/23) github.com/conformal/btcscript/stack.go asInt 100.00% (23/23) github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddData 100.00% (22/22) @@ -90,7 +90,7 @@ github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) github.com/conformal/btcscript/opcode.go parsedOpcode.alwaysIllegal 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) -github.com/conformal/btcscript/script.go @1321:17 100.00% (4/4) +github.com/conformal/btcscript/script.go @1329:17 100.00% (4/4) github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) @@ -171,12 +171,12 @@ github.com/conformal/btcscript/script.go HasCanonicalPushes 71.43% (5/7) github.com/conformal/btcscript/script.go sign 69.23% (18/26) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/10) github.com/conformal/btcscript/script.go CalcMultiSigStats 0.00% (0/8) -github.com/conformal/btcscript/script.go @578:34 0.00% (0/6) -github.com/conformal/btcscript/script.go @566:34 0.00% (0/4) -github.com/conformal/btcscript/script.go @611:34 0.00% (0/3) +github.com/conformal/btcscript/script.go @586:34 0.00% (0/6) +github.com/conformal/btcscript/script.go @574:34 0.00% (0/4) +github.com/conformal/btcscript/script.go @619:34 0.00% (0/3) github.com/conformal/btcscript/log.go UseLogger 0.00% (0/1) github.com/conformal/btcscript/opcode.go opcodeDisabled 0.00% (0/1) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) github.com/conformal/btcscript/opcode.go @1803:33 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 95.14% (1193/1254) +github.com/conformal/btcscript -------------------------- 95.15% (1197/1258) From 7d228846bd70dc452fee68fdf68d0e7b739f4be6 Mon Sep 17 00:00:00 2001 From: David Hill Date: Fri, 13 Jun 2014 11:34:47 -0400 Subject: [PATCH 133/174] sync tx_valid.json test data. --- data/tx_valid.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/tx_valid.json b/data/tx_valid.json index 40275cd1..aa8e5ca6 100644 --- a/data/tx_valid.json +++ b/data/tx_valid.json @@ -16,7 +16,7 @@ ["It is an OP_CHECKMULTISIG with an arbitrary extra byte stuffed into the signature at pos length - 2"], ["The dummy byte is fine however, so the NULLDUMMY flag should be happy"], [[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], -"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004A0048304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2bab01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004a0048304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2bab01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"], ["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], ["It is an OP_CHECKMULTISIG with the dummy value set to something other than an empty string"], From 79b6e51dff2d8250bfb3b6f8b1b9271f4ec3eb7e Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 2 Jul 2014 19:36:06 -0500 Subject: [PATCH 134/174] Update tests for recent btcutil.Address API change. --- script_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/script_test.go b/script_test.go index 40bde3ee..5c301365 100644 --- a/script_test.go +++ b/script_test.go @@ -2929,6 +2929,13 @@ func (b *bogusAddress) IsForNet(net *btcnet.Params) bool { return true // why not? } +// String simply returns an empty string. It exists to satsify the +// btcutil.Address interface. +func (b *bogusAddress) String() string { + return "" +} + + func TestPayToAddrScript(t *testing.T) { // 1MirQ9bwyQcGVJPwKUgapu5ouK2E2Ey4gX p2pkhMain, err := btcutil.NewAddressPubKeyHash([]byte{ From 5beafbd2d8be535c6a8f439b08d1c970da25b7bc Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 2 Jul 2014 19:37:49 -0500 Subject: [PATCH 135/174] goimports -w . --- address_test.go | 5 +++-- internal_test.go | 5 +++-- log.go | 3 ++- opcode.go | 7 ++++--- opcode_test.go | 3 ++- script.go | 5 +++-- script_test.go | 6 +++--- scriptbuilder_test.go | 3 ++- stack_test.go | 3 ++- 9 files changed, 24 insertions(+), 16 deletions(-) diff --git a/address_test.go b/address_test.go index f1d546b3..fbd4af76 100644 --- a/address_test.go +++ b/address_test.go @@ -5,11 +5,12 @@ package btcscript_test import ( "encoding/hex" + "reflect" + "testing" + "github.com/conformal/btcnet" "github.com/conformal/btcscript" "github.com/conformal/btcutil" - "reflect" - "testing" ) // decodeHex decodes the passed hex string and returns the resulting bytes. It diff --git a/internal_test.go b/internal_test.go index 66592235..f973879b 100644 --- a/internal_test.go +++ b/internal_test.go @@ -9,12 +9,13 @@ import ( "encoding/json" "errors" "fmt" - "github.com/conformal/btcutil" - "github.com/conformal/btcwire" "io/ioutil" "strconv" "strings" "testing" + + "github.com/conformal/btcutil" + "github.com/conformal/btcwire" ) // this file is present to export some internal interfaces so that we can diff --git a/log.go b/log.go index b1ca42a0..791bc355 100644 --- a/log.go +++ b/log.go @@ -6,8 +6,9 @@ package btcscript import ( "errors" - "github.com/conformal/btclog" "io" + + "github.com/conformal/btclog" ) // log is a logger that is initialized with no output filters. This diff --git a/opcode.go b/opcode.go index d63860bb..24f31acb 100644 --- a/opcode.go +++ b/opcode.go @@ -6,17 +6,18 @@ package btcscript import ( "bytes" - "code.google.com/p/go.crypto/ripemd160" "crypto/ecdsa" "crypto/sha1" "encoding/binary" "fmt" + "hash" + "math/big" + + "code.google.com/p/go.crypto/ripemd160" "github.com/conformal/btcec" "github.com/conformal/btcwire" "github.com/conformal/fastsha256" "github.com/davecgh/go-spew/spew" - "hash" - "math/big" ) // An opcode defines the information related to a btcscript opcode. diff --git a/opcode_test.go b/opcode_test.go index 2549973c..024f6323 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -6,10 +6,11 @@ package btcscript_test import ( "bytes" + "testing" + "github.com/conformal/btcscript" "github.com/conformal/btcwire" "github.com/davecgh/go-spew/spew" - "testing" ) // test scripts to test as many opcodes as possible. diff --git a/script.go b/script.go index 74df6fe7..ac8cfaf9 100644 --- a/script.go +++ b/script.go @@ -11,13 +11,14 @@ import ( "encoding/binary" "errors" "fmt" + "io" + "time" + "github.com/conformal/btcec" "github.com/conformal/btcnet" "github.com/conformal/btcutil" "github.com/conformal/btcwire" "github.com/davecgh/go-spew/spew" - "io" - "time" ) var ( diff --git a/script_test.go b/script_test.go index 5c301365..c7d09dd2 100644 --- a/script_test.go +++ b/script_test.go @@ -10,13 +10,14 @@ import ( "crypto/rand" "errors" "fmt" + "math/big" + "testing" + "github.com/conformal/btcec" "github.com/conformal/btcnet" "github.com/conformal/btcscript" "github.com/conformal/btcutil" "github.com/conformal/btcwire" - "math/big" - "testing" ) func TestPushedData(t *testing.T) { @@ -2935,7 +2936,6 @@ func (b *bogusAddress) String() string { return "" } - func TestPayToAddrScript(t *testing.T) { // 1MirQ9bwyQcGVJPwKUgapu5ouK2E2Ey4gX p2pkhMain, err := btcutil.NewAddressPubKeyHash([]byte{ diff --git a/scriptbuilder_test.go b/scriptbuilder_test.go index 847f53b8..41fd2e65 100644 --- a/scriptbuilder_test.go +++ b/scriptbuilder_test.go @@ -6,8 +6,9 @@ package btcscript_test import ( "bytes" - "github.com/conformal/btcscript" "testing" + + "github.com/conformal/btcscript" ) // TestScriptBuilderAddOp tests that pushing opcodes to a script via the diff --git a/stack_test.go b/stack_test.go index b9e4059d..0c1781fb 100644 --- a/stack_test.go +++ b/stack_test.go @@ -8,9 +8,10 @@ import ( "bytes" "errors" "fmt" - "github.com/conformal/btcscript" "math/big" "testing" + + "github.com/conformal/btcscript" ) type stackTest struct { From 3c2ae358b429ce6942e4aae94be3f12512b7f85b Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Tue, 8 Jul 2014 14:13:08 -0500 Subject: [PATCH 136/174] Add godoc reference badge to README.md. --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 4b14e99f..8676414f 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,9 @@ can be found at https://en.bitcoin.it/wiki/Script ## Documentation +[![GoDoc](https://godoc.org/github.com/conformal/btcscript?status.png)] +(http://godoc.org/github.com/conformal/btcscript) + Full `go doc` style documentation for the project can be viewed online without installing this package by using the GoDoc site [here](http://godoc.org/github.com/conformal/btcscript). From abafe9678bd1025b963036c9675285de40aa385a Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Tue, 8 Jul 2014 14:40:32 -0500 Subject: [PATCH 137/174] Use testable example and update doc.go README.md. This commit adds an example test file so it integrates nicely with Go's example tooling. This allows the example output to be tested as a part of running the normal Go tests to help ensure it doesn't get out of date with the code. It is also nice to have the example in one place rather than repeating it in doc.go and README.md. Links and information about the example have been included in README.md in place of the example. --- README.md | 17 ++++++++--------- doc.go | 23 ----------------------- example_test.go | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 32 deletions(-) create mode 100644 example_test.go diff --git a/README.md b/README.md index 8676414f..6ec84c41 100644 --- a/README.md +++ b/README.md @@ -23,15 +23,6 @@ the bitcoin transactions. This language is not turing complete although it is still fairly powerful. A description of the language can be found at https://en.bitcoin.it/wiki/Script -## Sample Use - -```Go - pkscript := txS.TxOut[origintxidx].PkScript - engine, err := btcscript.NewScript(sigScript, pkscript, txInIdx, - txValidator, timestamp.After(btcscript.Bip16Activation)) - err = engine.Execute() -``` - ## Documentation [![GoDoc](https://godoc.org/github.com/conformal/btcscript?status.png)] @@ -51,6 +42,14 @@ http://localhost:6060/pkg/github.com/conformal/btcscript $ go get github.com/conformal/btcscript ``` +## Examples + +* [Standard Pay-to-pubkey-hash Script] + (http://godoc.org/github.com/conformal/btcdb#example-PayToAddrScript) + Demonstrates creating a script which pays to a bitcoin address. It also + prints the created script hex and uses the DisasmString function to display + the disassembled script. + ## TODO - Increase test coverage to 100% diff --git a/doc.go b/doc.go index aa054ddc..dccc6a88 100644 --- a/doc.go +++ b/doc.go @@ -30,29 +30,6 @@ is used to prove the the spender is authorized to perform the transaction. One benefit of using a scripting language is added flexibility in specifying what conditions must be met in order to spend bitcoins. -Usage - -The usage of this package consists of creating a new script engine for a pair -of transaction inputs and outputs and using the engine to execute the scripts. - -The following function is an example of how to create and execute a script -engine to validate a transaction. - - // ValidateTx validates the txIdx'th input of tx. The output transaction - // corresponding to the this input is the txInIdx'th output of txIn. The - // block timestamp of tx is timestamp. - func ValidateTx(tx *btcwire.MsgTx, txIdx int, txIn *btcwire.MsgTx, txInIdx int, timestamp time.Time) { - pkScript := txIn.TxOut[txInIdx].PkScript - sigScript := tx.txIn[TxIdx] - var flags btcscript.ScriptFlags - if timestamp.After(btcscript.Bip16Activation) { - flags |= btcscript.ScriptBip16 - } - engine, err := btcscript.NewScript(sigScript, pkScript, txInIdx, - tx, flags) - return engine.Execute() - } - Errors Errors returned by this package are of the form btcscript.StackErrX where X diff --git a/example_test.go b/example_test.go new file mode 100644 index 00000000..3392cfac --- /dev/null +++ b/example_test.go @@ -0,0 +1,48 @@ +// Copyright (c) 2014 Conformal Systems LLC. +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcscript_test + +import ( + "fmt" + + "github.com/conformal/btcnet" + "github.com/conformal/btcscript" + "github.com/conformal/btcutil" +) + +// This example demonstrates creating a script which pays to a bitcoin address. +// It also prints the created script hex and uses the DisasmString function to +// display the disassembled script. +func ExamplePayToAddrScript() { + // Parse the address to send the coins to into a btcutil.Address + // which is useful to ensure the accuracy of the address and determine + // the address type. It is also required for the upcoming call to + // PayToAddrScript. + addressStr := "12gpXQVcCL2qhTNQgyLVdCFG2Qs2px98nV" + address, err := btcutil.DecodeAddress(addressStr, &btcnet.MainNetParams) + if err != nil { + fmt.Println(err) + return + } + + // Create a public key script that pays to the address. + script, err := btcscript.PayToAddrScript(address) + if err != nil { + fmt.Println(err) + return + } + fmt.Printf("Script Hex: %x\n", script) + + disasm, err := btcscript.DisasmString(script) + if err != nil { + fmt.Println(err) + return + } + fmt.Println("Script Disassembly:", disasm) + + // Output: + // Script Hex: 76a914128004ff2fcaf13b2b91eb654b1dc2b674f7ec6188ac + // Script Disassembly: OP_DUP OP_HASH160 128004ff2fcaf13b2b91eb654b1dc2b674f7ec61 OP_EQUALVERIFY OP_CHECKSIG +} From 631c7850ecbd02c1ddfca6580ee083cc3085a315 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Tue, 8 Jul 2014 14:43:50 -0500 Subject: [PATCH 138/174] Correct example link in README.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6ec84c41..09e3be59 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ $ go get github.com/conformal/btcscript ## Examples * [Standard Pay-to-pubkey-hash Script] - (http://godoc.org/github.com/conformal/btcdb#example-PayToAddrScript) + (http://godoc.org/github.com/conformal/btcscript#example-PayToAddrScript) Demonstrates creating a script which pays to a bitcoin address. It also prints the created script hex and uses the DisasmString function to display the disassembled script. From 95167204d9345662c93e36a8f067818ff6cb448d Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Tue, 8 Jul 2014 14:59:57 -0500 Subject: [PATCH 139/174] Add ExtractPkScriptAddrs examples. --- README.md | 4 ++++ example_test.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/README.md b/README.md index 09e3be59..db56a016 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,10 @@ $ go get github.com/conformal/btcscript prints the created script hex and uses the DisasmString function to display the disassembled script. +* [Extracting Details from Standard Scripts] + (http://godoc.org/github.com/conformal/btcscript#example-ExtractPkScriptAddrs) + Demonstrates extracting information from a standard public key script. + ## TODO - Increase test coverage to 100% diff --git a/example_test.go b/example_test.go index 3392cfac..933705c7 100644 --- a/example_test.go +++ b/example_test.go @@ -5,6 +5,7 @@ package btcscript_test import ( + "encoding/hex" "fmt" "github.com/conformal/btcnet" @@ -46,3 +47,31 @@ func ExamplePayToAddrScript() { // Script Hex: 76a914128004ff2fcaf13b2b91eb654b1dc2b674f7ec6188ac // Script Disassembly: OP_DUP OP_HASH160 128004ff2fcaf13b2b91eb654b1dc2b674f7ec61 OP_EQUALVERIFY OP_CHECKSIG } + +// This example demonstrates extracting information from a standard public key +// script. +func ExampleExtractPkScriptAddrs() { + // Start with a standard pay-to-pubkey-hash script. + scriptHex := "76a914128004ff2fcaf13b2b91eb654b1dc2b674f7ec6188ac" + script, err := hex.DecodeString(scriptHex) + if err != nil { + fmt.Println(err) + return + } + + // Extract and print details from the script. + scriptClass, addresses, reqSigs, err := btcscript.ExtractPkScriptAddrs( + script, &btcnet.MainNetParams) + if err != nil { + fmt.Println(err) + return + } + fmt.Println("Script Class:", scriptClass) + fmt.Println("Addresses:", addresses) + fmt.Println("Required Signatures:", reqSigs) + + // Output: + // Script Class: pubkeyhash + // Addresses: [12gpXQVcCL2qhTNQgyLVdCFG2Qs2px98nV] + // Required Signatures: 1 +} From 24c3873956a591f99c70973b3771cf0e75d97874 Mon Sep 17 00:00:00 2001 From: Michalis Kargakis Date: Thu, 31 Jul 2014 18:22:33 +0300 Subject: [PATCH 140/174] Add log testing 8/10 of SetLogWriter tested --- log_test.go | 51 +++++++++++++++++++++++++++++++++++++++++++++++ test_coverage.txt | 4 ++-- 2 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 log_test.go diff --git a/log_test.go b/log_test.go new file mode 100644 index 00000000..0a7527c6 --- /dev/null +++ b/log_test.go @@ -0,0 +1,51 @@ +// Copyright (c) 2013-2014 Conformal Systems LLC. +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcscript_test + +import ( + "errors" + "io" + "os" + "testing" + + "github.com/conformal/btcscript" +) + +func TestSetLogWriter(t *testing.T) { + tests := []struct { + name string + w io.Writer + level string + expected error + }{ + { + name: "nil writer", + w: nil, + level: "trace", + expected: errors.New("nil writer"), + }, + { + name: "invalid log level", + w: os.Stdout, + level: "wrong", + expected: errors.New("invalid log level"), + }, + { + name: "use off level", + w: os.Stdout, + level: "off", + expected: errors.New("Min level can't be greater than max. Got min: 6, max: 5"), + }, + } + + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + if err := btcscript.SetLogWriter(test.w, test.level); err.Error() != test.expected.Error() { + t.Errorf("SetLogWriter #%d (%s) wrong result\n"+ + "got: %x\nwant: %x", i, test.name, err, + test.expected) + } + } +} diff --git a/test_coverage.txt b/test_coverage.txt index d9638982..d34a6428 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -169,7 +169,7 @@ github.com/conformal/btcscript/script.go IsPushOnlyScript 75.00% (3/4) github.com/conformal/btcscript/script.go p2pkSignatureScript 75.00% (3/4) github.com/conformal/btcscript/script.go HasCanonicalPushes 71.43% (5/7) github.com/conformal/btcscript/script.go sign 69.23% (18/26) -github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/10) +github.com/conformal/btcscript/log.go SetLogWriter 0.00% (8/10) github.com/conformal/btcscript/script.go CalcMultiSigStats 0.00% (0/8) github.com/conformal/btcscript/script.go @586:34 0.00% (0/6) github.com/conformal/btcscript/script.go @574:34 0.00% (0/4) @@ -178,5 +178,5 @@ github.com/conformal/btcscript/log.go UseLogger 0.00% (0/1) github.com/conformal/btcscript/opcode.go opcodeDisabled 0.00% (0/1) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) github.com/conformal/btcscript/opcode.go @1803:33 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 95.15% (1197/1258) +github.com/conformal/btcscript -------------------------- 95.79% (1205/1258) From ef0ca7dff570d2c9c55d6480686c3b14130861f6 Mon Sep 17 00:00:00 2001 From: David Hill Date: Tue, 22 Jul 2014 21:51:38 -0400 Subject: [PATCH 141/174] sync bitcoind script tests --- data/script_invalid.json | 6 ++++++ data/script_valid.json | 4 ++++ opcode.go | 7 ++++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/data/script_invalid.json b/data/script_invalid.json index d623e974..e3e1ccbf 100644 --- a/data/script_invalid.json +++ b/data/script_invalid.json @@ -272,6 +272,9 @@ ["2147483647", "1ADD 1SUB 1", "We cannot do math on 5-byte integers, even if the result is 4-bytes"], ["2147483648", "1SUB 1", "We cannot do math on 5-byte integers, even if the result is 4-bytes"], +["2147483648 1", "BOOLOR 1", "We cannot do BOOLOR on 5-byte integers (but we can still do IF etc)"], +["2147483648 1", "BOOLAND 1", "We cannot do BOOLAND on 5-byte integers"], + ["1", "1 ENDIF", "ENDIF without IF"], ["1", "IF 1", "IF without ENDIF"], ["1 IF 1", "ENDIF", "IFs don't carry over"], @@ -349,6 +352,9 @@ "NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY"], +["0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21", "21 CHECKMULTISIG 1", "nPubKeys > 20"], +["0 'sig' 1 0", "CHECKMULTISIG 1", "nSigs > nPubKeys"], + ["NOP 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "Tests for Script.IsPushOnly()"], ["NOP1 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL"], diff --git a/data/script_valid.json b/data/script_valid.json index 7546a3b1..082c65ef 100644 --- a/data/script_valid.json +++ b/data/script_valid.json @@ -10,6 +10,8 @@ [" 1 2 ", "2 EQUALVERIFY 1 EQUAL"], ["1", ""], +["0x02 0x01 0x00", "", "all bytes are significant, not only the last one"], +["0x09 0x00000000 0x00000000 0x10", "", "equals zero when cast to Int64"], ["0x01 0x0b", "11 EQUAL", "push 1 byte"], ["0x02 0x417a", "'Az' EQUAL"], @@ -64,6 +66,7 @@ ["0", "IF RETURN ENDIF 1", "RETURN only works if executed"], ["1 1", "VERIFY"], +["1 0x05 0x01 0x00 0x00 0x00 0x00", "VERIFY", "values >4 bytes can be cast to boolean"], ["10 0 11 TOALTSTACK DROP FROMALTSTACK", "ADD 21 EQUAL"], ["'gavin_was_here' TOALTSTACK 11 FROMALTSTACK", "'gavin_was_here' EQUALVERIFY 11 EQUAL"], @@ -126,6 +129,7 @@ ["-9223372036854775807", "SIZE 8 EQUAL"], ["'abcdefghijklmnopqrstuvwxyz'", "SIZE 26 EQUAL"], +["42", "SIZE 1 EQUALVERIFY 42 EQUAL", "SIZE does not consume argument"], ["2 -2 ADD", "0 EQUAL"], ["2147483647 -2147483647 ADD", "0 EQUAL"], diff --git a/opcode.go b/opcode.go index 24f31acb..a278b438 100644 --- a/opcode.go +++ b/opcode.go @@ -1858,9 +1858,14 @@ func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error { if err != nil { return err } - // PopInt promises that the int returned is 32 bit. nsig := int(numSignatures.Int64()) + if nsig < 0 { + return fmt.Errorf("number of signatures %d is less than 0", nsig) + } + if nsig > npk { + return fmt.Errorf("more signatures than pubkeys: %d > %d", nsig, npk) + } sigStrings := make([][]byte, nsig) signatures := make([]sig, 0, nsig) From 55ad967b4d6699b511b7d941a7a192536a8c56aa Mon Sep 17 00:00:00 2001 From: Michalis Kargakis Date: Sun, 3 Aug 2014 23:30:37 +0300 Subject: [PATCH 142/174] Complete SetLogWriter testing --- log_test.go | 23 +++++++++++++++++++---- test_coverage.txt | 6 +++--- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/log_test.go b/log_test.go index 0a7527c6..ade92316 100644 --- a/log_test.go +++ b/log_test.go @@ -38,14 +38,29 @@ func TestSetLogWriter(t *testing.T) { level: "off", expected: errors.New("Min level can't be greater than max. Got min: 6, max: 5"), }, + { + name: "pass", + w: os.Stdout, + level: "debug", + expected: nil, + }, } t.Logf("Running %d tests", len(tests)) for i, test := range tests { - if err := btcscript.SetLogWriter(test.w, test.level); err.Error() != test.expected.Error() { - t.Errorf("SetLogWriter #%d (%s) wrong result\n"+ - "got: %x\nwant: %x", i, test.name, err, - test.expected) + err := btcscript.SetLogWriter(test.w, test.level) + if err != nil { + if err.Error() != test.expected.Error() { + t.Errorf("SetLogWriter #%d (%s) wrong result\n"+ + "got: %x\nwant: %x", i, test.name, err, + test.expected) + } + } else { + if test.expected != nil { + t.Errorf("SetLogWriter #%d (%s) wrong result\n"+ + "got: %x\nwant: %x", i, test.name, err, + test.expected) + } } } } diff --git a/test_coverage.txt b/test_coverage.txt index d34a6428..40536a8a 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -23,6 +23,7 @@ github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) github.com/conformal/btcscript/script.go typeOfScript 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) +github.com\conformal\btcscript/log.go SetLogWriter 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) @@ -132,6 +133,7 @@ github.com/conformal/btcscript/opcode.go init 100.00% (1/1) github.com/conformal/btcscript/script.go payToPubKeyHashScript 100.00% (1/1) github.com/conformal/btcscript/script.go payToScriptHashScript 100.00% (1/1) github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) +github.com\conformal\btcscript/log.go UseLogger 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) @@ -169,14 +171,12 @@ github.com/conformal/btcscript/script.go IsPushOnlyScript 75.00% (3/4) github.com/conformal/btcscript/script.go p2pkSignatureScript 75.00% (3/4) github.com/conformal/btcscript/script.go HasCanonicalPushes 71.43% (5/7) github.com/conformal/btcscript/script.go sign 69.23% (18/26) -github.com/conformal/btcscript/log.go SetLogWriter 0.00% (8/10) github.com/conformal/btcscript/script.go CalcMultiSigStats 0.00% (0/8) github.com/conformal/btcscript/script.go @586:34 0.00% (0/6) github.com/conformal/btcscript/script.go @574:34 0.00% (0/4) github.com/conformal/btcscript/script.go @619:34 0.00% (0/3) -github.com/conformal/btcscript/log.go UseLogger 0.00% (0/1) github.com/conformal/btcscript/opcode.go opcodeDisabled 0.00% (0/1) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) github.com/conformal/btcscript/opcode.go @1803:33 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 95.79% (1205/1258) +github.com/conformal/btcscript -------------------------- 96.03% (1208/1258) From 6ae916bd3704a7d0f74b833860768a22c27c20c4 Mon Sep 17 00:00:00 2001 From: Michalis Kargakis Date: Fri, 8 Aug 2014 14:46:15 +0300 Subject: [PATCH 143/174] More tests Tests for IsPushOnlyScript, HasCanonicalPushes, and CalcMultiSigStats --- script_test.go | 132 ++++++++++++++++++++++++++++++++++++++++++++++ test_coverage.txt | 8 +-- 2 files changed, 136 insertions(+), 4 deletions(-) diff --git a/script_test.go b/script_test.go index c7d09dd2..f7ce15e9 100644 --- a/script_test.go +++ b/script_test.go @@ -4623,3 +4623,135 @@ func TestSignTxOutput(t *testing.T) { } } } + +func TestCalcMultiSigStats(t *testing.T) { + tests := []struct { + name string + script []byte + expected error + }{ + { + name: "short script", + script: []byte{ + 0x04, 0x67, 0x08, 0xaf, 0xdb, 0x0f, 0xe5, 0x54, + 0x82, 0x71, 0x96, 0x7f, 0x1a, 0x67, 0x13, 0x0b, + 0x71, 0x05, 0xcd, 0x6a, 0x82, 0x8e, 0x03, 0x90, + 0x9a, 0x67, 0x96, 0x2e, 0x0e, 0xa1, 0xf6, 0x1d, + }, + expected: btcscript.StackErrShortScript, + }, + { + name: "stack underflow", + script: []byte{ + btcscript.OP_RETURN, + btcscript.OP_PUSHDATA1, + 0x29, + 0x04, 0x67, 0x08, 0xaf, 0xdb, 0x0f, 0xe5, 0x54, + 0x82, 0x71, 0x96, 0x7f, 0x1a, 0x67, 0x13, 0x0b, + 0x71, 0x05, 0xcd, 0x6a, 0x82, 0x8e, 0x03, 0x90, + 0x9a, 0x67, 0x96, 0x2e, 0x0e, 0xa1, 0xf6, 0x1d, + 0xeb, 0x64, 0x9f, 0x6b, 0xc3, 0xf4, 0xce, 0xf3, + 0x08, + }, + expected: btcscript.StackErrUnderflow, + }, + { + name: "multisig script", + script: []uint8{ + btcscript.OP_FALSE, + btcscript.OP_DATA_72, + 0x30, 0x45, 0x02, 0x20, 0x10, + 0x6a, 0x3e, 0x4e, 0xf0, 0xb5, + 0x1b, 0x76, 0x4a, 0x28, 0x87, + 0x22, 0x62, 0xff, 0xef, 0x55, + 0x84, 0x65, 0x14, 0xda, 0xcb, + 0xdc, 0xbb, 0xdd, 0x65, 0x2c, + 0x84, 0x9d, 0x39, 0x5b, 0x43, + 0x84, 0x02, 0x21, 0x00, 0xe0, + 0x3a, 0xe5, 0x54, 0xc3, 0xcb, + 0xb4, 0x06, 0x00, 0xd3, 0x1d, + 0xd4, 0x6f, 0xc3, 0x3f, 0x25, + 0xe4, 0x7b, 0xf8, 0x52, 0x5b, + 0x1f, 0xe0, 0x72, 0x82, 0xe3, + 0xb6, 0xec, 0xb5, 0xf3, 0xbb, + 0x28, 0x01, + btcscript.OP_CODESEPARATOR, + btcscript.OP_TRUE, + btcscript.OP_DATA_33, + 0x02, 0x32, 0xab, 0xdc, 0x89, + 0x3e, 0x7f, 0x06, 0x31, 0x36, + 0x4d, 0x7f, 0xd0, 0x1c, 0xb3, + 0x3d, 0x24, 0xda, 0x45, 0x32, + 0x9a, 0x00, 0x35, 0x7b, 0x3a, + 0x78, 0x86, 0x21, 0x1a, 0xb4, + 0x14, 0xd5, 0x5a, + btcscript.OP_TRUE, + btcscript.OP_CHECKMULTISIG, + }, + expected: nil, + }, + } + + for i, test := range tests { + if _, _, err := btcscript.CalcMultiSigStats(test.script); err != test.expected { + t.Errorf("CalcMultiSigStats #%d (%s) wrong result\n"+ + "got: %x\nwant: %x", i, test.name, err, + test.expected) + } + } +} + +func TestHasCanonicalPushes(t *testing.T) { + tests := []struct { + name string + script []byte + expected bool + }{ + { + name: "does not parse", + script: []byte{ + 0x04, 0x67, 0x08, 0xaf, 0xdb, 0x0f, 0xe5, 0x54, + 0x82, 0x71, 0x96, 0x7f, 0x1a, 0x67, 0x13, 0x0b, + 0x71, 0x05, 0xcd, 0x6a, 0x82, 0x8e, 0x03, 0x90, + 0x9a, 0x67, 0x96, 0x2e, 0x0e, 0xa1, 0xf6, 0x1d, + }, + expected: false, + }, + { + name: "non-canonical push", + script: []byte{btcscript.OP_PUSHDATA1, 4, 1, 2, 3, 4}, + expected: false, + }, + } + + for i, test := range tests { + if btcscript.HasCanonicalPushes(test.script) != test.expected { + t.Errorf("HasCanonicalPushes #%d (%s) wrong result\n"+ + "got: %x\nwant: %x", i, test.name, true, + test.expected) + } + } +} + +func TestIsPushOnlyScript(t *testing.T) { + test := struct { + name string + script []byte + expected bool + }{ + name: "does not parse", + script: []byte{ + 0x04, 0x67, 0x08, 0xaf, 0xdb, 0x0f, 0xe5, 0x54, + 0x82, 0x71, 0x96, 0x7f, 0x1a, 0x67, 0x13, 0x0b, + 0x71, 0x05, 0xcd, 0x6a, 0x82, 0x8e, 0x03, 0x90, + 0x9a, 0x67, 0x96, 0x2e, 0x0e, 0xa1, 0xf6, 0x1d, + }, + expected: false, + } + + if btcscript.IsPushOnlyScript(test.script) != test.expected { + t.Errorf("IsPushOnlyScript (%s) wrong result\n"+ + "got: %x\nwant: %x", test.name, true, + test.expected) + } +} diff --git a/test_coverage.txt b/test_coverage.txt index 40536a8a..efe0cb10 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -42,6 +42,7 @@ github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) github.com/conformal/btcscript/script.go Script.CheckErrorCondition 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) +github.com/conformal/btcscript/script.go CalcMultiSigStats 100.00% (8/8) github.com/conformal/btcscript/script.go Script.Execute 100.00% (8/8) github.com/conformal/btcscript/script.go MultiSigScript 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) @@ -52,6 +53,7 @@ github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddInt64 100.00 github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) +github.com/conformal/btcscript/script.go HasCanonicalPushes 100.00% (7/7) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddUint64 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) @@ -92,6 +94,7 @@ github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) github.com/conformal/btcscript/opcode.go parsedOpcode.alwaysIllegal 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) github.com/conformal/btcscript/script.go @1329:17 100.00% (4/4) +github.com/conformal/btcscript/script.go IsPushOnlyScript 100.00% (4/4) github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) @@ -167,16 +170,13 @@ github.com/conformal/btcscript/script.go signTxOutputCustomReader 87.50% (7/8) github.com/conformal/btcscript/script.go expectedInputs 85.71% (6/7) github.com/conformal/btcscript/script.go unparseScript 85.71% (6/7) github.com/conformal/btcscript/script.go SignTxOutput 80.00% (12/15) -github.com/conformal/btcscript/script.go IsPushOnlyScript 75.00% (3/4) github.com/conformal/btcscript/script.go p2pkSignatureScript 75.00% (3/4) -github.com/conformal/btcscript/script.go HasCanonicalPushes 71.43% (5/7) github.com/conformal/btcscript/script.go sign 69.23% (18/26) -github.com/conformal/btcscript/script.go CalcMultiSigStats 0.00% (0/8) github.com/conformal/btcscript/script.go @586:34 0.00% (0/6) github.com/conformal/btcscript/script.go @574:34 0.00% (0/4) github.com/conformal/btcscript/script.go @619:34 0.00% (0/3) github.com/conformal/btcscript/opcode.go opcodeDisabled 0.00% (0/1) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) github.com/conformal/btcscript/opcode.go @1803:33 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 96.03% (1208/1258) +github.com/conformal/btcscript -------------------------- 96.90% (1219/1258) From 95cd1b97fa823f2e8d5f481cdaab149deb356ff1 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Aug 2014 00:32:16 -0500 Subject: [PATCH 144/174] Make the OP_FALSE constant untyped. This makes it consistent with the rest of the opcode constants. --- opcode.go | 516 +++++++++++++++++++++++++++--------------------------- 1 file changed, 258 insertions(+), 258 deletions(-) diff --git a/opcode.go b/opcode.go index a278b438..1617aa86 100644 --- a/opcode.go +++ b/opcode.go @@ -36,264 +36,264 @@ type opcode struct { // in bitcoind and in most if not all other references and software related to // handling BTC scripts. const ( - OP_FALSE byte = 0 // AKA OP_0 - OP_0 = 0 - OP_DATA_1 = 1 - OP_DATA_2 = 2 - OP_DATA_3 = 3 - OP_DATA_4 = 4 - OP_DATA_5 = 5 - OP_DATA_6 = 6 - OP_DATA_7 = 7 - OP_DATA_8 = 8 - OP_DATA_9 = 9 - OP_DATA_10 = 10 - OP_DATA_11 = 11 - OP_DATA_12 = 12 - OP_DATA_13 = 13 - OP_DATA_14 = 14 - OP_DATA_15 = 15 - OP_DATA_16 = 16 - OP_DATA_17 = 17 - OP_DATA_18 = 18 - OP_DATA_19 = 19 - OP_DATA_20 = 20 - OP_DATA_21 = 21 - OP_DATA_22 = 22 - OP_DATA_23 = 23 - OP_DATA_24 = 24 - OP_DATA_25 = 25 - OP_DATA_26 = 26 - OP_DATA_27 = 27 - OP_DATA_28 = 28 - OP_DATA_29 = 29 - OP_DATA_30 = 30 - OP_DATA_31 = 31 - OP_DATA_32 = 32 - OP_DATA_33 = 33 - OP_DATA_34 = 34 - OP_DATA_35 = 35 - OP_DATA_36 = 36 - OP_DATA_37 = 37 - OP_DATA_38 = 38 - OP_DATA_39 = 39 - OP_DATA_40 = 40 - OP_DATA_41 = 41 - OP_DATA_42 = 42 - OP_DATA_43 = 43 - OP_DATA_44 = 44 - OP_DATA_45 = 45 - OP_DATA_46 = 46 - OP_DATA_47 = 47 - OP_DATA_48 = 48 - OP_DATA_49 = 49 - OP_DATA_50 = 50 - OP_DATA_51 = 51 - OP_DATA_52 = 52 - OP_DATA_53 = 53 - OP_DATA_54 = 54 - OP_DATA_55 = 55 - OP_DATA_56 = 56 - OP_DATA_57 = 57 - OP_DATA_58 = 58 - OP_DATA_59 = 59 - OP_DATA_60 = 60 - OP_DATA_61 = 61 - OP_DATA_62 = 62 - OP_DATA_63 = 63 - OP_DATA_64 = 64 - OP_DATA_65 = 65 - OP_DATA_66 = 66 - OP_DATA_67 = 67 - OP_DATA_68 = 68 - OP_DATA_69 = 69 - OP_DATA_70 = 70 - OP_DATA_71 = 71 - OP_DATA_72 = 72 - OP_DATA_73 = 73 - OP_DATA_74 = 74 - OP_DATA_75 = 75 - OP_PUSHDATA1 = 76 - OP_PUSHDATA2 = 77 - OP_PUSHDATA4 = 78 - OP_1NEGATE = 79 - OP_RESERVED = 80 - OP_1 = 81 // AKA OP_TRUE - OP_TRUE = 81 - OP_2 = 82 - OP_3 = 83 - OP_4 = 84 - OP_5 = 85 - OP_6 = 86 - OP_7 = 87 - OP_8 = 88 - OP_9 = 89 - OP_10 = 90 - OP_11 = 91 - OP_12 = 92 - OP_13 = 93 - OP_14 = 94 - OP_15 = 95 - OP_16 = 96 - OP_NOP = 97 - OP_VER = 98 - OP_IF = 99 - OP_NOTIF = 100 - OP_VERIF = 101 - OP_VERNOTIF = 102 - OP_ELSE = 103 - OP_ENDIF = 104 - OP_VERIFY = 105 - OP_RETURN = 106 - OP_TOALTSTACK = 107 - OP_FROMALTSTACK = 108 - OP_2DROP = 109 - OP_2DUP = 110 - OP_3DUP = 111 - OP_2OVER = 112 - OP_2ROT = 113 - OP_2SWAP = 114 - OP_IFDUP = 115 - OP_DEPTH = 116 - OP_DROP = 117 - OP_DUP = 118 - OP_NIP = 119 - OP_OVER = 120 - OP_PICK = 121 - OP_ROLL = 122 - OP_ROT = 123 - OP_SWAP = 124 - OP_TUCK = 125 - OP_CAT = 126 - OP_SUBSTR = 127 - OP_LEFT = 128 - OP_RIGHT = 129 - OP_SIZE = 130 - OP_INVERT = 131 - OP_AND = 132 - OP_OR = 133 - OP_XOR = 134 - OP_EQUAL = 135 - OP_EQUALVERIFY = 136 - OP_RESERVED1 = 137 - OP_RESERVED2 = 138 - OP_1ADD = 139 - OP_1SUB = 140 - OP_2MUL = 141 - OP_2DIV = 142 - OP_NEGATE = 143 - OP_ABS = 144 - OP_NOT = 145 - OP_0NOTEQUAL = 146 - OP_ADD = 147 - OP_SUB = 148 - OP_MUL = 149 - OP_DIV = 150 - OP_MOD = 151 - OP_LSHIFT = 152 - OP_RSHIFT = 153 - OP_BOOLAND = 154 - OP_BOOLOR = 155 - OP_NUMEQUAL = 156 - OP_NUMEQUALVERIFY = 157 - OP_NUMNOTEQUAL = 158 - OP_LESSTHAN = 159 - OP_GREATERTHAN = 160 - OP_LESSTHANOREQUAL = 161 - OP_GREATERTHANOREQUAL = 162 - OP_MIN = 163 - OP_MAX = 164 - OP_WITHIN = 165 - OP_RIPEMD160 = 166 - OP_SHA1 = 167 - OP_SHA256 = 168 - OP_HASH160 = 169 - OP_HASH256 = 170 - OP_CODESEPARATOR = 171 - OP_CHECKSIG = 172 - OP_CHECKSIGVERIFY = 173 - OP_CHECKMULTISIG = 174 - OP_CHECKMULTISIGVERIFY = 175 - OP_NOP1 = 176 - OP_NOP2 = 177 - OP_NOP3 = 178 - OP_NOP4 = 179 - OP_NOP5 = 180 - OP_NOP6 = 181 - OP_NOP7 = 182 - OP_NOP8 = 183 - OP_NOP9 = 184 - OP_NOP10 = 185 - OP_UNKNOWN186 = 186 - OP_UNKNOWN187 = 187 - OP_UNKNOWN188 = 188 - OP_UNKNOWN189 = 189 - OP_UNKNOWN190 = 190 - OP_UNKNOWN191 = 191 - OP_UNKNOWN192 = 192 - OP_UNKNOWN193 = 193 - OP_UNKNOWN194 = 194 - OP_UNKNOWN195 = 195 - OP_UNKNOWN196 = 196 - OP_UNKNOWN197 = 197 - OP_UNKNOWN198 = 198 - OP_UNKNOWN199 = 199 - OP_UNKNOWN200 = 200 - OP_UNKNOWN201 = 201 - OP_UNKNOWN202 = 202 - OP_UNKNOWN203 = 203 - OP_UNKNOWN204 = 204 - OP_UNKNOWN205 = 205 - OP_UNKNOWN206 = 206 - OP_UNKNOWN207 = 207 - OP_UNKNOWN208 = 208 - OP_UNKNOWN209 = 209 - OP_UNKNOWN210 = 210 - OP_UNKNOWN211 = 211 - OP_UNKNOWN212 = 212 - OP_UNKNOWN213 = 213 - OP_UNKNOWN214 = 214 - OP_UNKNOWN215 = 215 - OP_UNKNOWN216 = 216 - OP_UNKNOWN217 = 217 - OP_UNKNOWN218 = 218 - OP_UNKNOWN219 = 219 - OP_UNKNOWN220 = 220 - OP_UNKNOWN221 = 221 - OP_UNKNOWN222 = 222 - OP_UNKNOWN223 = 223 - OP_UNKNOWN224 = 224 - OP_UNKNOWN225 = 225 - OP_UNKNOWN226 = 226 - OP_UNKNOWN227 = 227 - OP_UNKNOWN228 = 228 - OP_UNKNOWN229 = 229 - OP_UNKNOWN230 = 230 - OP_UNKNOWN231 = 231 - OP_UNKNOWN232 = 232 - OP_UNKNOWN233 = 233 - OP_UNKNOWN234 = 234 - OP_UNKNOWN235 = 235 - OP_UNKNOWN236 = 236 - OP_UNKNOWN237 = 237 - OP_UNKNOWN238 = 238 - OP_UNKNOWN239 = 239 - OP_UNKNOWN240 = 240 - OP_UNKNOWN241 = 241 - OP_UNKNOWN242 = 242 - OP_UNKNOWN243 = 243 - OP_UNKNOWN244 = 244 - OP_UNKNOWN245 = 245 - OP_UNKNOWN246 = 246 - OP_UNKNOWN247 = 247 - OP_UNKNOWN248 = 248 - OP_UNKNOWN249 = 249 - OP_UNKNOWN250 = 250 - OP_UNKNOWN251 = 251 - OP_UNKNOWN252 = 252 - OP_PUBKEYHASH = 253 // bitcoind internal, for completeness - OP_PUBKEY = 254 // bitcoind internal, for completeness - OP_INVALIDOPCODE = 255 // bitcoind internal, for completeness + OP_FALSE = 0 // AKA OP_0 + OP_0 = 0 + OP_DATA_1 = 1 + OP_DATA_2 = 2 + OP_DATA_3 = 3 + OP_DATA_4 = 4 + OP_DATA_5 = 5 + OP_DATA_6 = 6 + OP_DATA_7 = 7 + OP_DATA_8 = 8 + OP_DATA_9 = 9 + OP_DATA_10 = 10 + OP_DATA_11 = 11 + OP_DATA_12 = 12 + OP_DATA_13 = 13 + OP_DATA_14 = 14 + OP_DATA_15 = 15 + OP_DATA_16 = 16 + OP_DATA_17 = 17 + OP_DATA_18 = 18 + OP_DATA_19 = 19 + OP_DATA_20 = 20 + OP_DATA_21 = 21 + OP_DATA_22 = 22 + OP_DATA_23 = 23 + OP_DATA_24 = 24 + OP_DATA_25 = 25 + OP_DATA_26 = 26 + OP_DATA_27 = 27 + OP_DATA_28 = 28 + OP_DATA_29 = 29 + OP_DATA_30 = 30 + OP_DATA_31 = 31 + OP_DATA_32 = 32 + OP_DATA_33 = 33 + OP_DATA_34 = 34 + OP_DATA_35 = 35 + OP_DATA_36 = 36 + OP_DATA_37 = 37 + OP_DATA_38 = 38 + OP_DATA_39 = 39 + OP_DATA_40 = 40 + OP_DATA_41 = 41 + OP_DATA_42 = 42 + OP_DATA_43 = 43 + OP_DATA_44 = 44 + OP_DATA_45 = 45 + OP_DATA_46 = 46 + OP_DATA_47 = 47 + OP_DATA_48 = 48 + OP_DATA_49 = 49 + OP_DATA_50 = 50 + OP_DATA_51 = 51 + OP_DATA_52 = 52 + OP_DATA_53 = 53 + OP_DATA_54 = 54 + OP_DATA_55 = 55 + OP_DATA_56 = 56 + OP_DATA_57 = 57 + OP_DATA_58 = 58 + OP_DATA_59 = 59 + OP_DATA_60 = 60 + OP_DATA_61 = 61 + OP_DATA_62 = 62 + OP_DATA_63 = 63 + OP_DATA_64 = 64 + OP_DATA_65 = 65 + OP_DATA_66 = 66 + OP_DATA_67 = 67 + OP_DATA_68 = 68 + OP_DATA_69 = 69 + OP_DATA_70 = 70 + OP_DATA_71 = 71 + OP_DATA_72 = 72 + OP_DATA_73 = 73 + OP_DATA_74 = 74 + OP_DATA_75 = 75 + OP_PUSHDATA1 = 76 + OP_PUSHDATA2 = 77 + OP_PUSHDATA4 = 78 + OP_1NEGATE = 79 + OP_RESERVED = 80 + OP_1 = 81 // AKA OP_TRUE + OP_TRUE = 81 + OP_2 = 82 + OP_3 = 83 + OP_4 = 84 + OP_5 = 85 + OP_6 = 86 + OP_7 = 87 + OP_8 = 88 + OP_9 = 89 + OP_10 = 90 + OP_11 = 91 + OP_12 = 92 + OP_13 = 93 + OP_14 = 94 + OP_15 = 95 + OP_16 = 96 + OP_NOP = 97 + OP_VER = 98 + OP_IF = 99 + OP_NOTIF = 100 + OP_VERIF = 101 + OP_VERNOTIF = 102 + OP_ELSE = 103 + OP_ENDIF = 104 + OP_VERIFY = 105 + OP_RETURN = 106 + OP_TOALTSTACK = 107 + OP_FROMALTSTACK = 108 + OP_2DROP = 109 + OP_2DUP = 110 + OP_3DUP = 111 + OP_2OVER = 112 + OP_2ROT = 113 + OP_2SWAP = 114 + OP_IFDUP = 115 + OP_DEPTH = 116 + OP_DROP = 117 + OP_DUP = 118 + OP_NIP = 119 + OP_OVER = 120 + OP_PICK = 121 + OP_ROLL = 122 + OP_ROT = 123 + OP_SWAP = 124 + OP_TUCK = 125 + OP_CAT = 126 + OP_SUBSTR = 127 + OP_LEFT = 128 + OP_RIGHT = 129 + OP_SIZE = 130 + OP_INVERT = 131 + OP_AND = 132 + OP_OR = 133 + OP_XOR = 134 + OP_EQUAL = 135 + OP_EQUALVERIFY = 136 + OP_RESERVED1 = 137 + OP_RESERVED2 = 138 + OP_1ADD = 139 + OP_1SUB = 140 + OP_2MUL = 141 + OP_2DIV = 142 + OP_NEGATE = 143 + OP_ABS = 144 + OP_NOT = 145 + OP_0NOTEQUAL = 146 + OP_ADD = 147 + OP_SUB = 148 + OP_MUL = 149 + OP_DIV = 150 + OP_MOD = 151 + OP_LSHIFT = 152 + OP_RSHIFT = 153 + OP_BOOLAND = 154 + OP_BOOLOR = 155 + OP_NUMEQUAL = 156 + OP_NUMEQUALVERIFY = 157 + OP_NUMNOTEQUAL = 158 + OP_LESSTHAN = 159 + OP_GREATERTHAN = 160 + OP_LESSTHANOREQUAL = 161 + OP_GREATERTHANOREQUAL = 162 + OP_MIN = 163 + OP_MAX = 164 + OP_WITHIN = 165 + OP_RIPEMD160 = 166 + OP_SHA1 = 167 + OP_SHA256 = 168 + OP_HASH160 = 169 + OP_HASH256 = 170 + OP_CODESEPARATOR = 171 + OP_CHECKSIG = 172 + OP_CHECKSIGVERIFY = 173 + OP_CHECKMULTISIG = 174 + OP_CHECKMULTISIGVERIFY = 175 + OP_NOP1 = 176 + OP_NOP2 = 177 + OP_NOP3 = 178 + OP_NOP4 = 179 + OP_NOP5 = 180 + OP_NOP6 = 181 + OP_NOP7 = 182 + OP_NOP8 = 183 + OP_NOP9 = 184 + OP_NOP10 = 185 + OP_UNKNOWN186 = 186 + OP_UNKNOWN187 = 187 + OP_UNKNOWN188 = 188 + OP_UNKNOWN189 = 189 + OP_UNKNOWN190 = 190 + OP_UNKNOWN191 = 191 + OP_UNKNOWN192 = 192 + OP_UNKNOWN193 = 193 + OP_UNKNOWN194 = 194 + OP_UNKNOWN195 = 195 + OP_UNKNOWN196 = 196 + OP_UNKNOWN197 = 197 + OP_UNKNOWN198 = 198 + OP_UNKNOWN199 = 199 + OP_UNKNOWN200 = 200 + OP_UNKNOWN201 = 201 + OP_UNKNOWN202 = 202 + OP_UNKNOWN203 = 203 + OP_UNKNOWN204 = 204 + OP_UNKNOWN205 = 205 + OP_UNKNOWN206 = 206 + OP_UNKNOWN207 = 207 + OP_UNKNOWN208 = 208 + OP_UNKNOWN209 = 209 + OP_UNKNOWN210 = 210 + OP_UNKNOWN211 = 211 + OP_UNKNOWN212 = 212 + OP_UNKNOWN213 = 213 + OP_UNKNOWN214 = 214 + OP_UNKNOWN215 = 215 + OP_UNKNOWN216 = 216 + OP_UNKNOWN217 = 217 + OP_UNKNOWN218 = 218 + OP_UNKNOWN219 = 219 + OP_UNKNOWN220 = 220 + OP_UNKNOWN221 = 221 + OP_UNKNOWN222 = 222 + OP_UNKNOWN223 = 223 + OP_UNKNOWN224 = 224 + OP_UNKNOWN225 = 225 + OP_UNKNOWN226 = 226 + OP_UNKNOWN227 = 227 + OP_UNKNOWN228 = 228 + OP_UNKNOWN229 = 229 + OP_UNKNOWN230 = 230 + OP_UNKNOWN231 = 231 + OP_UNKNOWN232 = 232 + OP_UNKNOWN233 = 233 + OP_UNKNOWN234 = 234 + OP_UNKNOWN235 = 235 + OP_UNKNOWN236 = 236 + OP_UNKNOWN237 = 237 + OP_UNKNOWN238 = 238 + OP_UNKNOWN239 = 239 + OP_UNKNOWN240 = 240 + OP_UNKNOWN241 = 241 + OP_UNKNOWN242 = 242 + OP_UNKNOWN243 = 243 + OP_UNKNOWN244 = 244 + OP_UNKNOWN245 = 245 + OP_UNKNOWN246 = 246 + OP_UNKNOWN247 = 247 + OP_UNKNOWN248 = 248 + OP_UNKNOWN249 = 249 + OP_UNKNOWN250 = 250 + OP_UNKNOWN251 = 251 + OP_UNKNOWN252 = 252 + OP_PUBKEYHASH = 253 // bitcoind internal, for completeness + OP_PUBKEY = 254 // bitcoind internal, for completeness + OP_INVALIDOPCODE = 255 // bitcoind internal, for completeness ) // conditional execution constants From da080e1598fabe49a11c60532ced743c76529a8f Mon Sep 17 00:00:00 2001 From: Jonathan Gillham Date: Mon, 25 Aug 2014 21:09:23 +0100 Subject: [PATCH 145/174] Changed privkey to privKey for consistency. --- script.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/script.go b/script.go index ac8cfaf9..238e866f 100644 --- a/script.go +++ b/script.go @@ -1090,21 +1090,21 @@ func MultiSigScript(pubkeys []*btcutil.AddressPubKey, nrequired int) ([]byte, er } // SignatureScript creates an input signature script for tx to spend -// BTC sent from a previous output to the owner of privkey. tx must +// BTC sent from a previous output to the owner of privKey. tx must // include all transaction inputs and outputs, however txin scripts are // allowed to be filled or empty. The returned script is calculated to // be used as the idx'th txin sigscript for tx. subscript is the PkScript -// of the previous output being used as the idx'th input. privkey is +// of the previous output being used as the idx'th input. privKey is // serialized in either a compressed or uncompressed format based on -// compress. This format must match the same format used to generate +// compress. This format must match the same format used to generate // the payment address, or the script validation will fail. -func SignatureScript(tx *btcwire.MsgTx, idx int, subscript []byte, hashType byte, privkey *ecdsa.PrivateKey, compress bool) ([]byte, error) { - sig, err := signTxOutput(tx, idx, subscript, hashType, privkey) +func SignatureScript(tx *btcwire.MsgTx, idx int, subscript []byte, hashType byte, privKey *ecdsa.PrivateKey, compress bool) ([]byte, error) { + sig, err := signTxOutput(tx, idx, subscript, hashType, privKey) if err != nil { return nil, err } - pk := (*btcec.PublicKey)(&privkey.PublicKey) + pk := (*btcec.PublicKey)(&privKey.PublicKey) var pkData []byte if compress { pkData = pk.SerializeCompressed() From 516db23576aef5476a76cb735592f12fe8c905b8 Mon Sep 17 00:00:00 2001 From: Jonathan Gillham Date: Mon, 25 Aug 2014 21:14:19 +0100 Subject: [PATCH 146/174] Replaced privkey in entire codebase. --- script.go | 4 ++-- script_test.go | 56 +++++++++++++++++++++++++------------------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/script.go b/script.go index 238e866f..099ef7b7 100644 --- a/script.go +++ b/script.go @@ -1137,8 +1137,8 @@ func signTxOutputCustomReader(reader io.Reader, tx *btcwire.MsgTx, idx int, return append((&btcec.Signature{R: r, S: s}).Serialize(), hashType), nil } -func p2pkSignatureScript(tx *btcwire.MsgTx, idx int, subScript []byte, hashType byte, privkey *ecdsa.PrivateKey) ([]byte, error) { - sig, err := signTxOutput(tx, idx, subScript, hashType, privkey) +func p2pkSignatureScript(tx *btcwire.MsgTx, idx int, subScript []byte, hashType byte, privKey *ecdsa.PrivateKey) ([]byte, error) { + sig, err := signTxOutput(tx, idx, subScript, hashType, privKey) if err != nil { return nil, err } diff --git a/script_test.go b/script_test.go index f7ce15e9..63c66314 100644 --- a/script_test.go +++ b/script_test.go @@ -2537,7 +2537,7 @@ var coinbaseOutPoint = &btcwire.OutPoint{ // Pregenerated private key, with associated public key and pkScripts // for the uncompressed and compressed hash160. var ( - privkeyD = []byte{0x6b, 0x0f, 0xd8, 0xda, 0x54, 0x22, 0xd0, 0xb7, + privKeyD = []byte{0x6b, 0x0f, 0xd8, 0xda, 0x54, 0x22, 0xd0, 0xb7, 0xb4, 0xfc, 0x4e, 0x55, 0xd4, 0x88, 0x42, 0xb3, 0xa1, 0x65, 0xac, 0x70, 0x7f, 0x3d, 0xa4, 0x39, 0x5e, 0xcb, 0x3b, 0xb0, 0xd6, 0x0e, 0x06, 0x92} @@ -2766,7 +2766,7 @@ var SigScriptTests = []TstSigScript{ // created for the MsgTxs in txTests, since they come from the blockchain // and we don't have the private keys. func TestSignatureScript(t *testing.T) { - privkey := &ecdsa.PrivateKey{ + privKey := &ecdsa.PrivateKey{ PublicKey: ecdsa.PublicKey{ Curve: btcec.S256(), X: new(big.Int), @@ -2774,9 +2774,9 @@ func TestSignatureScript(t *testing.T) { }, D: new(big.Int), } - privkey.D.SetBytes(privkeyD) - privkey.PublicKey.X.SetBytes(pubkeyX) - privkey.PublicKey.Y.SetBytes(pubkeyY) + privKey.D.SetBytes(privKeyD) + privKey.PublicKey.X.SetBytes(pubkeyX) + privKey.PublicKey.Y.SetBytes(pubkeyY) nexttest: for i := range SigScriptTests { @@ -2802,7 +2802,7 @@ nexttest: } script, err = btcscript.SignatureScript(tx, idx, SigScriptTests[i].inputs[j].txout.PkScript, - SigScriptTests[i].hashtype, privkey, + SigScriptTests[i].hashtype, privKey, SigScriptTests[i].compress) if (err == nil) != SigScriptTests[i].inputs[j].sigscriptGenerates { @@ -3369,7 +3369,7 @@ func TestSignTxOutput(t *testing.T) { key, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { - t.Errorf("failed to make privkey for %s: %v", + t.Errorf("failed to make privKey for %s: %v", msg, err) break } @@ -3407,7 +3407,7 @@ func TestSignTxOutput(t *testing.T) { key, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { - t.Errorf("failed to make privkey for %s: %v", + t.Errorf("failed to make privKey for %s: %v", msg, err) break } @@ -3469,7 +3469,7 @@ func TestSignTxOutput(t *testing.T) { key, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { - t.Errorf("failed to make privkey for %s: %v", + t.Errorf("failed to make privKey for %s: %v", msg, err) break } @@ -3508,7 +3508,7 @@ func TestSignTxOutput(t *testing.T) { key, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { - t.Errorf("failed to make privkey for %s: %v", + t.Errorf("failed to make privKey for %s: %v", msg, err) break } @@ -3570,7 +3570,7 @@ func TestSignTxOutput(t *testing.T) { key, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { - t.Errorf("failed to make privkey for %s: %v", + t.Errorf("failed to make privKey for %s: %v", msg, err) break } @@ -3609,7 +3609,7 @@ func TestSignTxOutput(t *testing.T) { key, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { - t.Errorf("failed to make privkey for %s: %v", + t.Errorf("failed to make privKey for %s: %v", msg, err) break } @@ -3671,7 +3671,7 @@ func TestSignTxOutput(t *testing.T) { key, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { - t.Errorf("failed to make privkey for %s: %v", + t.Errorf("failed to make privKey for %s: %v", msg, err) break } @@ -3710,7 +3710,7 @@ func TestSignTxOutput(t *testing.T) { key, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { - t.Errorf("failed to make privkey for %s: %v", + t.Errorf("failed to make privKey for %s: %v", msg, err) break } @@ -3772,7 +3772,7 @@ func TestSignTxOutput(t *testing.T) { key, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { - t.Errorf("failed to make privkey for %s: %v", + t.Errorf("failed to make privKey for %s: %v", msg, err) break } @@ -3830,7 +3830,7 @@ func TestSignTxOutput(t *testing.T) { key, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { - t.Errorf("failed to make privkey for %s: %v", + t.Errorf("failed to make privKey for %s: %v", msg, err) break } @@ -3913,7 +3913,7 @@ func TestSignTxOutput(t *testing.T) { key, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { - t.Errorf("failed to make privkey for %s: %v", + t.Errorf("failed to make privKey for %s: %v", msg, err) break } @@ -3971,7 +3971,7 @@ func TestSignTxOutput(t *testing.T) { key, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { - t.Errorf("failed to make privkey for %s: %v", + t.Errorf("failed to make privKey for %s: %v", msg, err) break } @@ -4053,7 +4053,7 @@ func TestSignTxOutput(t *testing.T) { key, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { - t.Errorf("failed to make privkey for %s: %v", + t.Errorf("failed to make privKey for %s: %v", msg, err) break } @@ -4111,7 +4111,7 @@ func TestSignTxOutput(t *testing.T) { key, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { - t.Errorf("failed to make privkey for %s: %v", + t.Errorf("failed to make privKey for %s: %v", msg, err) break } @@ -4193,7 +4193,7 @@ func TestSignTxOutput(t *testing.T) { key, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { - t.Errorf("failed to make privkey for %s: %v", + t.Errorf("failed to make privKey for %s: %v", msg, err) break } @@ -4251,7 +4251,7 @@ func TestSignTxOutput(t *testing.T) { key, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { - t.Errorf("failed to make privkey for %s: %v", + t.Errorf("failed to make privKey for %s: %v", msg, err) break } @@ -4333,7 +4333,7 @@ func TestSignTxOutput(t *testing.T) { key1, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { - t.Errorf("failed to make privkey for %s: %v", + t.Errorf("failed to make privKey for %s: %v", msg, err) break } @@ -4351,7 +4351,7 @@ func TestSignTxOutput(t *testing.T) { key2, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { - t.Errorf("failed to make privkey 2 for %s: %v", + t.Errorf("failed to make privKey 2 for %s: %v", msg, err) break } @@ -4412,7 +4412,7 @@ func TestSignTxOutput(t *testing.T) { key1, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { - t.Errorf("failed to make privkey for %s: %v", + t.Errorf("failed to make privKey for %s: %v", msg, err) break } @@ -4430,7 +4430,7 @@ func TestSignTxOutput(t *testing.T) { key2, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { - t.Errorf("failed to make privkey 2 for %s: %v", + t.Errorf("failed to make privKey 2 for %s: %v", msg, err) break } @@ -4521,7 +4521,7 @@ func TestSignTxOutput(t *testing.T) { key1, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { - t.Errorf("failed to make privkey for %s: %v", + t.Errorf("failed to make privKey for %s: %v", msg, err) break } @@ -4539,7 +4539,7 @@ func TestSignTxOutput(t *testing.T) { key2, err := ecdsa.GenerateKey(btcec.S256(), rand.Reader) if err != nil { - t.Errorf("failed to make privkey 2 for %s: %v", + t.Errorf("failed to make privKey 2 for %s: %v", msg, err) break } From 2803ea17c2a7ec5b806b9085c2a7949cee5355f1 Mon Sep 17 00:00:00 2001 From: David Hill Date: Fri, 29 Aug 2014 09:27:46 -0400 Subject: [PATCH 147/174] Remove the use of go-spew. --- opcode.go | 15 +++-- opcode_test.go | 10 ++- script.go | 5 +- stack.go | 12 ++++ test_coverage.txt | 154 +++++++++++++++++++++++----------------------- 5 files changed, 105 insertions(+), 91 deletions(-) diff --git a/opcode.go b/opcode.go index 1617aa86..e36821a3 100644 --- a/opcode.go +++ b/opcode.go @@ -9,6 +9,7 @@ import ( "crypto/ecdsa" "crypto/sha1" "encoding/binary" + "encoding/hex" "fmt" "hash" "math/big" @@ -17,7 +18,6 @@ import ( "github.com/conformal/btcec" "github.com/conformal/btcwire" "github.com/conformal/fastsha256" - "github.com/davecgh/go-spew/spew" ) // An opcode defines the information related to a btcscript opcode. @@ -1802,10 +1802,15 @@ func opcodeCheckSig(op *parsedOpcode, s *Script) error { } log.Tracef("%v", newLogClosure(func() string { - return fmt.Sprintf("op_checksig pubKey %v\npk.x: %v\n "+ - "pk.y: %v\n r: %v\n s: %v\ncheckScriptHash %v", - spew.Sdump(pkStr), pubKey.X, pubKey.Y, - signature.R, signature.S, spew.Sdump(hash)) + return fmt.Sprintf("op_checksig\n"+ + "pubKey:\n%v"+ + "pubKey.X: %v\n"+ + "pubKey.Y: %v\n"+ + "signature.R: %v\n"+ + "signature.S: %v\n"+ + "checkScriptHash:\n%v", + hex.Dump(pkStr), pubKey.X, pubKey.Y, + signature.R, signature.S, hex.Dump(hash)) })) ok := ecdsa.Verify(pubKey.ToECDSA(), hash, signature.R, signature.S) s.dstack.PushBool(ok) diff --git a/opcode_test.go b/opcode_test.go index 024f6323..d36b2b1d 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -10,7 +10,6 @@ import ( "github.com/conformal/btcscript" "github.com/conformal/btcwire" - "github.com/davecgh/go-spew/spew" ) // test scripts to test as many opcodes as possible. @@ -4364,14 +4363,13 @@ func testOpcode(t *testing.T, test *detailedTest) { after := engine.GetStack() if !stacksEqual(after, test.after) { - t.Errorf("Stacks not equal after %s:\ngot: %v\n exp: %v", - test.name, spew.Sdump(after), spew.Sdump(test.after)) + t.Errorf("Stacks not equal after %s:\ngot:\n%vexp:\n%v", + test.name, after, test.after) } altafter := engine.GetAltStack() if !stacksEqual(altafter, test.altafter) { - t.Errorf("AltStacks not equal after %s:\n got: %v\nexp: %v", - test.name, spew.Sdump(altafter), - spew.Sdump(test.altafter)) + t.Errorf("AltStacks not equal after %s:\n got:\n%vexp:\n%v", + test.name, altafter, test.altafter) } } diff --git a/script.go b/script.go index 099ef7b7..e77a70d5 100644 --- a/script.go +++ b/script.go @@ -18,7 +18,6 @@ import ( "github.com/conformal/btcnet" "github.com/conformal/btcutil" "github.com/conformal/btcwire" - "github.com/davecgh/go-spew/spew" ) var ( @@ -589,10 +588,10 @@ func (s *Script) Execute() (err error) { // if we're tracing, dump the stacks. if s.dstack.Depth() != 0 { - dstr = "Stack\n" + spew.Sdump(s.dstack) + dstr = "Stack:\n" + s.dstack.String() } if s.astack.Depth() != 0 { - astr = "AltStack\n" + spew.Sdump(s.astack) + astr = "AltStack:\n" + s.astack.String() } return dstr + astr diff --git a/stack.go b/stack.go index f2c96c5f..ab82ac6a 100644 --- a/stack.go +++ b/stack.go @@ -5,6 +5,7 @@ package btcscript import ( + "encoding/hex" "math/big" ) @@ -355,3 +356,14 @@ func (s *Stack) RollN(n int) error { return nil } + +// String returns the stack in a readable format. +func (s *Stack) String() string { + var result string + + for _, stack := range s.stk { + result += hex.Dump(stack) + } + + return result +} diff --git a/test_coverage.txt b/test_coverage.txt index efe0cb10..dcc570f4 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -1,9 +1,8 @@ -github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 100.00% (62/62) github.com/conformal/btcscript/script.go calcScriptHash 100.00% (39/39) github.com/conformal/btcscript/script.go Script.Step 100.00% (37/37) -github.com/conformal/btcscript/opcode.go opcodeCheckSig 100.00% (29/29) github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (29/29) +github.com/conformal/btcscript/opcode.go opcodeCheckSig 100.00% (29/29) github.com/conformal/btcscript/address.go ExtractPkScriptAddrs 100.00% (27/27) github.com/conformal/btcscript/script.go NewScript 100.00% (25/25) github.com/conformal/btcscript/script.go CalcScriptInfo 100.00% (25/25) @@ -18,12 +17,12 @@ github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (13/13) github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) -github.com/conformal/btcscript/script.go PayToAddrScript 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) +github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) +github.com/conformal/btcscript/script.go PayToAddrScript 100.00% (11/11) github.com/conformal/btcscript/script.go typeOfScript 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) -github.com\conformal\btcscript/log.go SetLogWriter 100.00% (10/10) +github.com/conformal/btcscript/log.go SetLogWriter 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) @@ -36,50 +35,50 @@ github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) github.com/conformal/btcscript/script.go PushedData 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) -github.com/conformal/btcscript/script.go SignatureScript 100.00% (9/9) -github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) -github.com/conformal/btcscript/script.go Script.CheckErrorCondition 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) -github.com/conformal/btcscript/script.go CalcMultiSigStats 100.00% (8/8) +github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/script.go Script.CheckErrorCondition 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) +github.com/conformal/btcscript/script.go SignatureScript 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) +github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) github.com/conformal/btcscript/script.go Script.Execute 100.00% (8/8) +github.com/conformal/btcscript/script.go CalcMultiSigStats 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) github.com/conformal/btcscript/script.go MultiSigScript 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddInt64 100.00% (7/7) -github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) github.com/conformal/btcscript/script.go HasCanonicalPushes 100.00% (7/7) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddUint64 100.00% (7/7) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddInt64 100.00% (7/7) +github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) +github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodePick 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodePick 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) @@ -89,94 +88,95 @@ github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/ github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) github.com/conformal/btcscript/script.go isNullData 100.00% (4/4) github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) +github.com/conformal/btcscript/script.go IsPushOnlyScript 100.00% (4/4) github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) -github.com/conformal/btcscript/opcode.go parsedOpcode.alwaysIllegal 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) +github.com/conformal/btcscript/opcode.go parsedOpcode.alwaysIllegal 100.00% (4/4) github.com/conformal/btcscript/script.go @1329:17 100.00% (4/4) -github.com/conformal/btcscript/script.go IsPushOnlyScript 100.00% (4/4) github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) -github.com/conformal/btcscript/script.go asSmallInt 100.00% (3/3) -github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) github.com/conformal/btcscript/script.go setStack 100.00% (3/3) -github.com/conformal/btcscript/script.go ScriptClass.String 100.00% (3/3) github.com/conformal/btcscript/script.go isSmallInt 100.00% (3/3) -github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddOp 100.00% (2/2) -github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Reset 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) +github.com/conformal/btcscript/script.go asSmallInt 100.00% (3/3) +github.com/conformal/btcscript/script.go ScriptClass.String 100.00% (3/3) github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) +github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddOp 100.00% (2/2) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Reset 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) -github.com/conformal/btcscript/log.go init 100.00% (1/1) -github.com/conformal/btcscript/script.go signTxOutput 100.00% (1/1) -github.com/conformal/btcscript/script.go payToPubKeyScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) -github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go init 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) github.com/conformal/btcscript/script.go payToPubKeyHashScript 100.00% (1/1) github.com/conformal/btcscript/script.go payToScriptHashScript 100.00% (1/1) -github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com\conformal\btcscript/log.go UseLogger 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) -github.com/conformal/btcscript/scriptbuilder.go NewScriptBuilder 100.00% (1/1) +github.com/conformal/btcscript/script.go payToPubKeyScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go init 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) -github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) +github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/script.go signTxOutput 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) github.com/conformal/btcscript/script.go KeyClosure.GetKey 100.00% (1/1) github.com/conformal/btcscript/script.go ScriptClosure.GetScript 100.00% (1/1) +github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) +github.com/conformal/btcscript/log.go init 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) +github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) +github.com/conformal/btcscript/scriptbuilder.go NewScriptBuilder 100.00% (1/1) +github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.48% (65/66) github.com/conformal/btcscript/script.go mergeScripts 95.00% (19/20) github.com/conformal/btcscript/script.go canonicalPush 92.86% (13/14) github.com/conformal/btcscript/script.go signMultiSig 92.86% (13/14) github.com/conformal/btcscript/script.go mergeMultiSig 88.10% (37/42) github.com/conformal/btcscript/script.go signTxOutputCustomReader 87.50% (7/8) -github.com/conformal/btcscript/script.go expectedInputs 85.71% (6/7) github.com/conformal/btcscript/script.go unparseScript 85.71% (6/7) +github.com/conformal/btcscript/script.go expectedInputs 85.71% (6/7) github.com/conformal/btcscript/script.go SignTxOutput 80.00% (12/15) github.com/conformal/btcscript/script.go p2pkSignatureScript 75.00% (3/4) github.com/conformal/btcscript/script.go sign 69.23% (18/26) github.com/conformal/btcscript/script.go @586:34 0.00% (0/6) github.com/conformal/btcscript/script.go @574:34 0.00% (0/4) github.com/conformal/btcscript/script.go @619:34 0.00% (0/3) +github.com/conformal/btcscript/opcode.go @1803:33 0.00% (0/1) github.com/conformal/btcscript/opcode.go opcodeDisabled 0.00% (0/1) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript/opcode.go @1803:33 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 96.90% (1219/1258) +github.com/conformal/btcscript -------------------------- 96.83% (1222/1262) From edb006c11c5a25a8e2187435ef4ff61f0478442f Mon Sep 17 00:00:00 2001 From: Jonathan Gillham Date: Wed, 1 Oct 2014 13:57:27 +0100 Subject: [PATCH 148/174] Changed TxIn.PreviousOutpoint to TxIn.PreviousOutPoint after btcwire API change. --- internal_test.go | 4 ++-- opcode_test.go | 4 ++-- script_test.go | 48 ++++++++++++++++++++++++------------------------ 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/internal_test.go b/internal_test.go index f973879b..2bddf601 100644 --- a/internal_test.go +++ b/internal_test.go @@ -4019,7 +4019,7 @@ testloop: } for k, txin := range tx.MsgTx().TxIn { - pkScript, ok := prevOuts[txin.PreviousOutpoint] + pkScript, ok := prevOuts[txin.PreviousOutPoint] if !ok { t.Errorf("bad test (missing %dth input) %d:%v", k, i, test) @@ -4165,7 +4165,7 @@ testloop: } for k, txin := range tx.MsgTx().TxIn { - pkScript, ok := prevOuts[txin.PreviousOutpoint] + pkScript, ok := prevOuts[txin.PreviousOutPoint] if !ok { t.Errorf("bad test (missing %dth input) %d:%v", k, i, test) diff --git a/opcode_test.go b/opcode_test.go index d36b2b1d..0d95e571 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -484,7 +484,7 @@ func testScript(t *testing.T, script []byte, canonical bool) (err error) { Version: 1, TxIn: []*btcwire.TxIn{ { - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash{}, Index: 0xffffffff, }, @@ -4267,7 +4267,7 @@ func testOpcode(t *testing.T, test *detailedTest) { Version: 1, TxIn: []*btcwire.TxIn{ { - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash{}, Index: 0xffffffff, }, diff --git a/script_test.go b/script_test.go index 63c66314..5cddd495 100644 --- a/script_test.go +++ b/script_test.go @@ -129,7 +129,7 @@ var txTests = []txTest{ Version: 1, TxIn: []*btcwire.TxIn{ { - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0xc9, 0x97, 0xa5, 0xe5, 0x6e, 0x10, 0x41, 0x02, @@ -235,7 +235,7 @@ var txTests = []txTest{ Version: 1, TxIn: []*btcwire.TxIn{ { - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0xc9, 0x97, 0xa5, 0xe5, 0x6e, 0x10, 0x41, 0x02, @@ -341,7 +341,7 @@ var txTests = []txTest{ Version: 1, TxIn: []*btcwire.TxIn{ { - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0xc9, 0x97, 0xa5, 0xe5, 0x6e, 0x10, 0x41, 0x02, @@ -449,7 +449,7 @@ var txTests = []txTest{ Version: 1, TxIn: []*btcwire.TxIn{ { - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0xc9, 0x97, 0xa5, 0xe5, 0x6e, 0x10, 0x41, 0x02, @@ -558,7 +558,7 @@ var txTests = []txTest{ Version: 1, TxIn: []*btcwire.TxIn{ { - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x5f, 0x38, 0x6c, 0x8a, 0x38, 0x42, 0xc9, 0xa9, @@ -664,7 +664,7 @@ var txTests = []txTest{ Version: 1, TxIn: []*btcwire.TxIn{ { - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0xfe, 0x15, 0x62, 0xc4, 0x8b, 0x3a, 0xa6, 0x37, @@ -712,7 +712,7 @@ var txTests = []txTest{ Sequence: 4294967295, }, { - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x2a, 0xc7, 0xee, 0xf8, 0xa9, 0x62, 0x2d, 0xda, @@ -838,7 +838,7 @@ var txTests = []txTest{ Version: 1, TxIn: []*btcwire.TxIn{ { - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0xf6, 0x04, 0x4c, 0x0a, 0xd4, 0x85, 0xf6, 0x33, @@ -880,7 +880,7 @@ var txTests = []txTest{ Sequence: 4294967295, }, { - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x9c, 0x6a, 0xf0, 0xdf, 0x66, 0x69, 0xbc, 0xde, @@ -968,7 +968,7 @@ var txTests = []txTest{ Version: 1, TxIn: []*btcwire.TxIn{ { - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x37, 0xb1, 0x7d, 0x76, 0x38, 0x51, 0xcd, 0x1a, @@ -1006,7 +1006,7 @@ var txTests = []txTest{ Sequence: 4294967295, }, { - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x37, 0xb1, 0x7d, 0x76, 0x38, 0x51, 0xcd, 0x1a, @@ -1091,7 +1091,7 @@ var txTests = []txTest{ Version: 1, TxIn: []*btcwire.TxIn{ { - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x37, 0xb1, 0x7d, 0x76, 0x38, 0x51, 0xcd, 0x1a, @@ -1129,7 +1129,7 @@ var txTests = []txTest{ Sequence: 4294967295, }, { - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x37, 0xb1, 0x7d, 0x76, 0x38, 0x51, 0xcd, 0x1a, @@ -1217,7 +1217,7 @@ var txTests = []txTest{ Version: 1, TxIn: []*btcwire.TxIn{ { - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x37, 0xb1, 0x7d, 0x76, 0x38, 0x51, 0xcd, 0x1a, @@ -1277,7 +1277,7 @@ var txTests = []txTest{ Version: 1, TxIn: []*btcwire.TxIn{ { - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x6d, 0x58, 0xf8, 0xa3, 0xaa, 0x43, 0x0b, 0x84, @@ -1343,7 +1343,7 @@ var txTests = []txTest{ Version: 1, TxIn: []*btcwire.TxIn{ { - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x6d, 0x58, 0xf8, 0xa3, 0xaa, 0x43, 0x0b, 0x84, @@ -1408,7 +1408,7 @@ var txTests = []txTest{ Version: 1, TxIn: []*btcwire.TxIn{ { - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x6d, 0x58, 0xf8, 0xa3, 0xaa, 0x43, 0x0b, 0x84, @@ -1467,7 +1467,7 @@ var txTests = []txTest{ Version: 1, TxIn: []*btcwire.TxIn{ { - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x6d, 0x58, 0xf8, 0xa3, 0xaa, 0x43, 0x0b, 0x84, @@ -1531,7 +1531,7 @@ var txTests = []txTest{ Version: 1, TxIn: []*btcwire.TxIn{ { - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0x6d, 0x58, 0xf8, 0xa3, 0xaa, 0x43, 0x0b, 0x84, @@ -2377,7 +2377,7 @@ func TestBadPC(t *testing.T) { Version: 1, TxIn: []*btcwire.TxIn{ { - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0xc9, 0x97, 0xa5, 0xe5, 0x6e, 0x10, 0x41, 0x02, @@ -2436,7 +2436,7 @@ func TestCheckErrorCondition(t *testing.T) { Version: 1, TxIn: []*btcwire.TxIn{ { - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash([32]byte{ 0xc9, 0x97, 0xa5, 0xe5, 0x6e, 0x10, 0x41, 0x02, @@ -3327,21 +3327,21 @@ func TestSignTxOutput(t *testing.T) { Version: 1, TxIn: []*btcwire.TxIn{ &btcwire.TxIn{ - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash{}, Index: 0, }, Sequence: 4294967295, }, &btcwire.TxIn{ - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash{}, Index: 1, }, Sequence: 4294967295, }, &btcwire.TxIn{ - PreviousOutpoint: btcwire.OutPoint{ + PreviousOutPoint: btcwire.OutPoint{ Hash: btcwire.ShaHash{}, Index: 2, }, From b89cabfb291ed60d64679f44626c13b0c4481af2 Mon Sep 17 00:00:00 2001 From: kac- <6b6163@gmail.com> Date: Sun, 5 Oct 2014 10:19:29 +0200 Subject: [PATCH 149/174] comment:script.go: ScriptDB->KeyDB --- script.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script.go b/script.go index e77a70d5..1da43589 100644 --- a/script.go +++ b/script.go @@ -1423,7 +1423,7 @@ type KeyDB interface { GetKey(btcutil.Address) (*ecdsa.PrivateKey, bool, error) } -// KeyClosure implements ScriptDB with a closure +// KeyClosure implements KeyDB with a closure type KeyClosure func(btcutil.Address) (*ecdsa.PrivateKey, bool, error) // GetKey implements KeyDB by returning the result of calling the closure From 9f47e9369c09fbc98f5e20bb5128321f4ba0d080 Mon Sep 17 00:00:00 2001 From: Jonathan Gillham Date: Fri, 10 Oct 2014 11:43:32 +0100 Subject: [PATCH 150/174] Fixed SignTxOutput doc spelling error. --- script.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script.go b/script.go index 1da43589..7db56536 100644 --- a/script.go +++ b/script.go @@ -1449,7 +1449,7 @@ func (sc ScriptClosure) GetScript(address btcutil.Address) ([]byte, error) { // SignTxOutput signs output idx of the given tx to resolve the script given in // pkScript with a signature type of hashType. Any keys required will be // looked up by calling getKey() with the string of the given address. -// Any pay-to-script-hash signatures will be similarly lookedu p by calling +// Any pay-to-script-hash signatures will be similarly looked up by calling // getScript. If previousScript is provided then the results in previousScript // will be merged in a type-dependant manner with the newly generated. // signature script. From 37ad7042b6f1f66566115a5ac196b6515b0203a9 Mon Sep 17 00:00:00 2001 From: Jonathan Gillham Date: Sat, 11 Oct 2014 20:55:28 +0100 Subject: [PATCH 151/174] Made hashType typed as SigHashType. --- opcode.go | 5 +++-- script.go | 34 +++++++++++++++++++--------------- script_test.go | 42 +++++++++++++++++++++--------------------- 3 files changed, 43 insertions(+), 38 deletions(-) diff --git a/opcode.go b/opcode.go index e36821a3..4fb85dd8 100644 --- a/opcode.go +++ b/opcode.go @@ -1771,7 +1771,7 @@ func opcodeCheckSig(op *parsedOpcode, s *Script) error { } // Trim off hashtype from the signature string. - hashType := sigStr[len(sigStr)-1] + hashType := SigHashType(sigStr[len(sigStr)-1]) sigStr = sigStr[:len(sigStr)-1] // Get script from the last OP_CODESEPARATOR and without any subsequent @@ -1932,7 +1932,8 @@ func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error { // check signatures. success := false - hash := calcScriptHash(script, signatures[i].ht, &s.tx, s.txidx) + hash := calcScriptHash(script, SigHashType(signatures[i].ht), + &s.tx, s.txidx) inner: // Find first pubkey that successfully validates signature. // we start off the search from the key that was successful diff --git a/script.go b/script.go index 7db56536..f2939fa2 100644 --- a/script.go +++ b/script.go @@ -145,13 +145,16 @@ var ErrUnsupportedAddress = errors.New("unsupported address type") // This timestamp corresponds to Sun Apr 1 00:00:00 UTC 2012. var Bip16Activation = time.Unix(1333238400, 0) +// SigHashType represents hash type bits at the end of a signature. +type SigHashType byte + // Hash type bits from the end of a signature. const ( - SigHashOld = 0x0 - SigHashAll = 0x1 - SigHashNone = 0x2 - SigHashSingle = 0x3 - SigHashAnyOneCanPay = 0x80 + SigHashOld SigHashType = 0x0 + SigHashAll SigHashType = 0x1 + SigHashNone SigHashType = 0x2 + SigHashSingle SigHashType = 0x3 + SigHashAnyOneCanPay SigHashType = 0x80 ) // These are the constants specified for maximums in individual scripts. @@ -805,7 +808,7 @@ func DisasmString(buf []byte) (string, error) { // calcScriptHash will, given the a script and hashtype for the current // scriptmachine, calculate the doubleSha256 hash of the transaction and // script to be used for signature signing and verification. -func calcScriptHash(script []parsedOpcode, hashType byte, tx *btcwire.MsgTx, idx int) []byte { +func calcScriptHash(script []parsedOpcode, hashType SigHashType, tx *btcwire.MsgTx, idx int) []byte { // remove all instances of OP_CODESEPARATOR still left in the script script = removeOpcode(script, OP_CODESEPARATOR) @@ -1097,7 +1100,7 @@ func MultiSigScript(pubkeys []*btcutil.AddressPubKey, nrequired int) ([]byte, er // serialized in either a compressed or uncompressed format based on // compress. This format must match the same format used to generate // the payment address, or the script validation will fail. -func SignatureScript(tx *btcwire.MsgTx, idx int, subscript []byte, hashType byte, privKey *ecdsa.PrivateKey, compress bool) ([]byte, error) { +func SignatureScript(tx *btcwire.MsgTx, idx int, subscript []byte, hashType SigHashType, privKey *ecdsa.PrivateKey, compress bool) ([]byte, error) { sig, err := signTxOutput(tx, idx, subscript, hashType, privKey) if err != nil { return nil, err @@ -1114,7 +1117,7 @@ func SignatureScript(tx *btcwire.MsgTx, idx int, subscript []byte, hashType byte return NewScriptBuilder().AddData(sig).AddData(pkData).Script(), nil } -func signTxOutput(tx *btcwire.MsgTx, idx int, subScript []byte, hashType byte, +func signTxOutput(tx *btcwire.MsgTx, idx int, subScript []byte, hashType SigHashType, key *ecdsa.PrivateKey) ([]byte, error) { return signTxOutputCustomReader(rand.Reader, tx, idx, subScript, @@ -1122,7 +1125,7 @@ func signTxOutput(tx *btcwire.MsgTx, idx int, subScript []byte, hashType byte, } func signTxOutputCustomReader(reader io.Reader, tx *btcwire.MsgTx, idx int, - subScript []byte, hashType byte, key *ecdsa.PrivateKey) ([]byte, error) { + subScript []byte, hashType SigHashType, key *ecdsa.PrivateKey) ([]byte, error) { parsedScript, err := parseScript(subScript) if err != nil { return nil, fmt.Errorf("cannot parse output script: %v", err) @@ -1133,10 +1136,11 @@ func signTxOutputCustomReader(reader io.Reader, tx *btcwire.MsgTx, idx int, return nil, fmt.Errorf("cannot sign tx input: %s", err) } - return append((&btcec.Signature{R: r, S: s}).Serialize(), hashType), nil + return append((&btcec.Signature{R: r, S: s}).Serialize(), + byte(hashType)), nil } -func p2pkSignatureScript(tx *btcwire.MsgTx, idx int, subScript []byte, hashType byte, privKey *ecdsa.PrivateKey) ([]byte, error) { +func p2pkSignatureScript(tx *btcwire.MsgTx, idx int, subScript []byte, hashType SigHashType, privKey *ecdsa.PrivateKey) ([]byte, error) { sig, err := signTxOutput(tx, idx, subScript, hashType, privKey) if err != nil { return nil, err @@ -1149,7 +1153,7 @@ func p2pkSignatureScript(tx *btcwire.MsgTx, idx int, subScript []byte, hashType // possible. It returns the generated script and a boolean if the script fulfils // the contract (i.e. nrequired signatures are provided). Since it is arguably // legal to not be able to sign any of the outputs, no error is returned. -func signMultiSig(tx *btcwire.MsgTx, idx int, subScript []byte, hashType byte, +func signMultiSig(tx *btcwire.MsgTx, idx int, subScript []byte, hashType SigHashType, addresses []btcutil.Address, nRequired int, kdb KeyDB) ([]byte, bool) { // We start with a single OP_FALSE to work around the (now standard) // but in the reference implementation that causes a spurious pop at @@ -1178,7 +1182,7 @@ func signMultiSig(tx *btcwire.MsgTx, idx int, subScript []byte, hashType byte, } func sign(net *btcnet.Params, tx *btcwire.MsgTx, idx int, subScript []byte, - hashType byte, kdb KeyDB, sdb ScriptDB) ([]byte, ScriptClass, + hashType SigHashType, kdb KeyDB, sdb ScriptDB) ([]byte, ScriptClass, []btcutil.Address, int, error) { class, addresses, nrequired, err := ExtractPkScriptAddrs(subScript, net) @@ -1355,7 +1359,7 @@ sigLoop: continue } tSig := sig[:len(sig)-1] - hashType := sig[len(sig)-1] + hashType := SigHashType(sig[len(sig)-1]) pSig, err := btcec.ParseDERSignature(tSig, btcec.S256()) if err != nil { @@ -1454,7 +1458,7 @@ func (sc ScriptClosure) GetScript(address btcutil.Address) ([]byte, error) { // will be merged in a type-dependant manner with the newly generated. // signature script. func SignTxOutput(net *btcnet.Params, tx *btcwire.MsgTx, idx int, - pkScript []byte, hashType byte, kdb KeyDB, sdb ScriptDB, + pkScript []byte, hashType SigHashType, kdb KeyDB, sdb ScriptDB, previousScript []byte) ([]byte, error) { sigScript, class, addresses, nrequired, err := sign(net, tx, idx, diff --git a/script_test.go b/script_test.go index 5cddd495..23ef4032 100644 --- a/script_test.go +++ b/script_test.go @@ -2518,7 +2518,7 @@ func TestCheckErrorCondition(t *testing.T) { type TstSigScript struct { name string inputs []TstInput - hashtype byte + hashType btcscript.SigHashType compress bool scriptAtWrongIndex bool } @@ -2577,7 +2577,7 @@ var SigScriptTests = []TstSigScript{ indexOutOfRange: false, }, }, - hashtype: btcscript.SigHashAll, + hashType: btcscript.SigHashAll, compress: false, scriptAtWrongIndex: false, }, @@ -2597,7 +2597,7 @@ var SigScriptTests = []TstSigScript{ indexOutOfRange: false, }, }, - hashtype: btcscript.SigHashAll, + hashType: btcscript.SigHashAll, compress: false, scriptAtWrongIndex: false, }, @@ -2611,7 +2611,7 @@ var SigScriptTests = []TstSigScript{ indexOutOfRange: false, }, }, - hashtype: btcscript.SigHashAll, + hashType: btcscript.SigHashAll, compress: true, scriptAtWrongIndex: false, }, @@ -2631,12 +2631,12 @@ var SigScriptTests = []TstSigScript{ indexOutOfRange: false, }, }, - hashtype: btcscript.SigHashAll, + hashType: btcscript.SigHashAll, compress: true, scriptAtWrongIndex: false, }, { - name: "hashtype SigHashNone", + name: "hashType SigHashNone", inputs: []TstInput{ { txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), @@ -2645,12 +2645,12 @@ var SigScriptTests = []TstSigScript{ indexOutOfRange: false, }, }, - hashtype: btcscript.SigHashNone, + hashType: btcscript.SigHashNone, compress: false, scriptAtWrongIndex: false, }, { - name: "hashtype SigHashSingle", + name: "hashType SigHashSingle", inputs: []TstInput{ { txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), @@ -2659,12 +2659,12 @@ var SigScriptTests = []TstSigScript{ indexOutOfRange: false, }, }, - hashtype: btcscript.SigHashSingle, + hashType: btcscript.SigHashSingle, compress: false, scriptAtWrongIndex: false, }, { - name: "hashtype SigHashAnyoneCanPay", + name: "hashType SigHashAnyoneCanPay", inputs: []TstInput{ { txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), @@ -2673,12 +2673,12 @@ var SigScriptTests = []TstSigScript{ indexOutOfRange: false, }, }, - hashtype: btcscript.SigHashAnyOneCanPay, + hashType: btcscript.SigHashAnyOneCanPay, compress: false, scriptAtWrongIndex: false, }, { - name: "hashtype non-standard", + name: "hashType non-standard", inputs: []TstInput{ { txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), @@ -2687,7 +2687,7 @@ var SigScriptTests = []TstSigScript{ indexOutOfRange: false, }, }, - hashtype: 0x04, + hashType: 0x04, compress: false, scriptAtWrongIndex: false, }, @@ -2701,7 +2701,7 @@ var SigScriptTests = []TstSigScript{ indexOutOfRange: false, }, }, - hashtype: btcscript.SigHashAll, + hashType: btcscript.SigHashAll, compress: true, scriptAtWrongIndex: false, }, @@ -2714,7 +2714,7 @@ var SigScriptTests = []TstSigScript{ indexOutOfRange: false, }, }, - hashtype: btcscript.SigHashAll, + hashType: btcscript.SigHashAll, compress: false, scriptAtWrongIndex: false, }, @@ -2734,7 +2734,7 @@ var SigScriptTests = []TstSigScript{ indexOutOfRange: false, }, }, - hashtype: btcscript.SigHashAll, + hashType: btcscript.SigHashAll, compress: false, scriptAtWrongIndex: true, }, @@ -2754,14 +2754,14 @@ var SigScriptTests = []TstSigScript{ indexOutOfRange: false, }, }, - hashtype: btcscript.SigHashAll, + hashType: btcscript.SigHashAll, compress: false, scriptAtWrongIndex: true, }, } // Test the sigscript generation for valid and invalid inputs, all -// hashtypes, and with and without compression. This test creates +// hashTypes, and with and without compression. This test creates // sigscripts to spend fake coinbase inputs, as sigscripts cannot be // created for the MsgTxs in txTests, since they come from the blockchain // and we don't have the private keys. @@ -2802,7 +2802,7 @@ nexttest: } script, err = btcscript.SignatureScript(tx, idx, SigScriptTests[i].inputs[j].txout.PkScript, - SigScriptTests[i].hashtype, privKey, + SigScriptTests[i].hashType, privKey, SigScriptTests[i].compress) if (err == nil) != SigScriptTests[i].inputs[j].sigscriptGenerates { @@ -3239,7 +3239,7 @@ func TestMultiSigScript(t *testing.T) { } func signAndCheck(msg string, tx *btcwire.MsgTx, idx int, pkScript []byte, - hashType byte, kdb btcscript.KeyDB, sdb btcscript.ScriptDB, + hashType btcscript.SigHashType, kdb btcscript.KeyDB, sdb btcscript.ScriptDB, previousScript []byte) error { sigScript, err := btcscript.SignTxOutput( @@ -3314,7 +3314,7 @@ func TestSignTxOutput(t *testing.T) { // make key // make script based on key. // sign with magic pixie dust. - hashTypes := []byte{ + hashTypes := []btcscript.SigHashType{ btcscript.SigHashOld, // no longer used but should act like all btcscript.SigHashAll, btcscript.SigHashNone, From c0c3d860d693c9d477c9d7c2ef8784c4b7b4c041 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Sun, 12 Oct 2014 16:40:09 -0500 Subject: [PATCH 152/174] Convert all StackErrX to ErrStackX. This commit changes all stack errors from the form of StackErrX to ErrStackX which is the expected form for standard Go code. --- doc.go | 2 +- internal_test.go | 526 +++++++++++++++++++++++------------------------ opcode.go | 32 +-- opcode_test.go | 336 +++++++++++++++--------------- script.go | 130 ++++++------ script_test.go | 40 ++-- stack.go | 16 +- stack_test.go | 48 ++--- 8 files changed, 565 insertions(+), 565 deletions(-) diff --git a/doc.go b/doc.go index dccc6a88..64d9e095 100644 --- a/doc.go +++ b/doc.go @@ -32,7 +32,7 @@ what conditions must be met in order to spend bitcoins. Errors -Errors returned by this package are of the form btcscript.StackErrX where X +Errors returned by this package are of the form btcscript.ErrStackX where X indicates the specific error. See Variables in the package documentation for a full list. */ diff --git a/internal_test.go b/internal_test.go index 2bddf601..8193dc59 100644 --- a/internal_test.go +++ b/internal_test.go @@ -99,7 +99,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_FALSE], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_1 short", @@ -107,7 +107,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_1], data: nil, }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_1", @@ -123,7 +123,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_1], data: make([]byte, 2), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_2 short", @@ -131,7 +131,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_2], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_2", @@ -147,7 +147,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_2], data: make([]byte, 3), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_3 short", @@ -155,7 +155,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_3], data: make([]byte, 2), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_3", @@ -171,7 +171,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_3], data: make([]byte, 4), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_4 short", @@ -179,7 +179,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_4], data: make([]byte, 3), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_4", @@ -195,7 +195,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_4], data: make([]byte, 5), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_5 short", @@ -203,7 +203,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_5], data: make([]byte, 4), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_5", @@ -219,7 +219,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_5], data: make([]byte, 6), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_6 short", @@ -227,7 +227,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_6], data: make([]byte, 5), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_6", @@ -243,7 +243,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_6], data: make([]byte, 7), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_7 short", @@ -251,7 +251,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_7], data: make([]byte, 6), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_7", @@ -267,7 +267,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_7], data: make([]byte, 8), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_8 short", @@ -275,7 +275,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_8], data: make([]byte, 7), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_8", @@ -291,7 +291,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_8], data: make([]byte, 9), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_9 short", @@ -299,7 +299,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_9], data: make([]byte, 8), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_9", @@ -315,7 +315,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_9], data: make([]byte, 10), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_10 short", @@ -323,7 +323,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_10], data: make([]byte, 9), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_10", @@ -339,7 +339,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_10], data: make([]byte, 11), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_11 short", @@ -347,7 +347,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_11], data: make([]byte, 10), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_11", @@ -363,7 +363,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_11], data: make([]byte, 12), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_12 short", @@ -371,7 +371,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_12], data: make([]byte, 11), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_12", @@ -387,7 +387,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_12], data: make([]byte, 13), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_13 short", @@ -395,7 +395,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_13], data: make([]byte, 12), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_13", @@ -411,7 +411,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_13], data: make([]byte, 14), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_14 short", @@ -419,7 +419,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_14], data: make([]byte, 13), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_14", @@ -435,7 +435,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_14], data: make([]byte, 15), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_15 short", @@ -443,7 +443,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_15], data: make([]byte, 14), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_15", @@ -459,7 +459,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_15], data: make([]byte, 16), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_16 short", @@ -467,7 +467,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_16], data: make([]byte, 15), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_16", @@ -483,7 +483,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_16], data: make([]byte, 17), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_17 short", @@ -491,7 +491,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_17], data: make([]byte, 16), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_17", @@ -507,7 +507,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_17], data: make([]byte, 18), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_18 short", @@ -515,7 +515,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_18], data: make([]byte, 17), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_18", @@ -531,7 +531,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_18], data: make([]byte, 19), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_19 short", @@ -539,7 +539,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_19], data: make([]byte, 18), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_19", @@ -555,7 +555,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_19], data: make([]byte, 20), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_20 short", @@ -563,7 +563,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_20], data: make([]byte, 19), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_20", @@ -579,7 +579,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_20], data: make([]byte, 21), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_21 short", @@ -587,7 +587,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_21], data: make([]byte, 20), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_21", @@ -603,7 +603,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_21], data: make([]byte, 22), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_22 short", @@ -611,7 +611,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_22], data: make([]byte, 21), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_22", @@ -627,7 +627,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_22], data: make([]byte, 23), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_23 short", @@ -635,7 +635,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_23], data: make([]byte, 22), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_23", @@ -651,7 +651,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_23], data: make([]byte, 24), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_24 short", @@ -659,7 +659,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_24], data: make([]byte, 23), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_24", @@ -675,7 +675,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_24], data: make([]byte, 25), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_25 short", @@ -683,7 +683,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_25], data: make([]byte, 24), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_25", @@ -699,7 +699,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_25], data: make([]byte, 26), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_26 short", @@ -707,7 +707,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_26], data: make([]byte, 25), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_26", @@ -723,7 +723,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_26], data: make([]byte, 27), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_27 short", @@ -731,7 +731,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_27], data: make([]byte, 26), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_27", @@ -747,7 +747,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_27], data: make([]byte, 28), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_28 short", @@ -755,7 +755,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_28], data: make([]byte, 27), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_28", @@ -771,7 +771,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_28], data: make([]byte, 29), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_29 short", @@ -779,7 +779,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_29], data: make([]byte, 28), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_29", @@ -795,7 +795,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_29], data: make([]byte, 30), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_30 short", @@ -803,7 +803,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_30], data: make([]byte, 29), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_30", @@ -819,7 +819,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_30], data: make([]byte, 31), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_31 short", @@ -827,7 +827,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_31], data: make([]byte, 30), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_31", @@ -843,7 +843,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_31], data: make([]byte, 32), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_32 short", @@ -851,7 +851,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_32], data: make([]byte, 31), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_32", @@ -867,7 +867,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_32], data: make([]byte, 33), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_33 short", @@ -875,7 +875,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_33], data: make([]byte, 32), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_33", @@ -891,7 +891,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_33], data: make([]byte, 34), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_34 short", @@ -899,7 +899,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_34], data: make([]byte, 33), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_34", @@ -915,7 +915,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_34], data: make([]byte, 35), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_35 short", @@ -923,7 +923,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_35], data: make([]byte, 34), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_35", @@ -939,7 +939,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_35], data: make([]byte, 36), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_36 short", @@ -947,7 +947,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_36], data: make([]byte, 35), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_36", @@ -963,7 +963,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_36], data: make([]byte, 37), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_37 short", @@ -971,7 +971,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_37], data: make([]byte, 36), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_37", @@ -987,7 +987,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_37], data: make([]byte, 38), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_38 short", @@ -995,7 +995,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_38], data: make([]byte, 37), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_38", @@ -1011,7 +1011,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_38], data: make([]byte, 39), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_39 short", @@ -1019,7 +1019,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_39], data: make([]byte, 38), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_39", @@ -1035,7 +1035,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_39], data: make([]byte, 40), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_40 short", @@ -1043,7 +1043,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_40], data: make([]byte, 39), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_40", @@ -1059,7 +1059,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_40], data: make([]byte, 41), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_41 short", @@ -1067,7 +1067,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_41], data: make([]byte, 40), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_41", @@ -1083,7 +1083,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_41], data: make([]byte, 42), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_42 short", @@ -1091,7 +1091,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_42], data: make([]byte, 41), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_42", @@ -1107,7 +1107,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_42], data: make([]byte, 43), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_43 short", @@ -1115,7 +1115,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_43], data: make([]byte, 42), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_43", @@ -1131,7 +1131,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_43], data: make([]byte, 44), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_44 short", @@ -1139,7 +1139,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_44], data: make([]byte, 43), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_44", @@ -1155,7 +1155,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_44], data: make([]byte, 45), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_45 short", @@ -1163,7 +1163,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_45], data: make([]byte, 44), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_45", @@ -1179,7 +1179,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_45], data: make([]byte, 46), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_46 short", @@ -1187,7 +1187,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_46], data: make([]byte, 45), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_46", @@ -1203,7 +1203,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_46], data: make([]byte, 47), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_47 short", @@ -1211,7 +1211,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_47], data: make([]byte, 46), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_47", @@ -1227,7 +1227,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_47], data: make([]byte, 48), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_48 short", @@ -1235,7 +1235,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_48], data: make([]byte, 47), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_48", @@ -1251,7 +1251,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_48], data: make([]byte, 49), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_49 short", @@ -1259,7 +1259,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_49], data: make([]byte, 48), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_49", @@ -1275,7 +1275,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_49], data: make([]byte, 50), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_50 short", @@ -1283,7 +1283,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_50], data: make([]byte, 49), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_50", @@ -1299,7 +1299,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_50], data: make([]byte, 51), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_51 short", @@ -1307,7 +1307,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_51], data: make([]byte, 50), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_51", @@ -1323,7 +1323,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_51], data: make([]byte, 52), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_52 short", @@ -1331,7 +1331,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_52], data: make([]byte, 51), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_52", @@ -1347,7 +1347,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_52], data: make([]byte, 53), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_53 short", @@ -1355,7 +1355,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_53], data: make([]byte, 52), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_53", @@ -1371,7 +1371,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_53], data: make([]byte, 54), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_54 short", @@ -1379,7 +1379,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_54], data: make([]byte, 53), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_54", @@ -1395,7 +1395,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_54], data: make([]byte, 55), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_55 short", @@ -1403,7 +1403,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_55], data: make([]byte, 54), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_55", @@ -1419,7 +1419,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_55], data: make([]byte, 56), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_56 short", @@ -1427,7 +1427,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_56], data: make([]byte, 55), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_56", @@ -1443,7 +1443,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_56], data: make([]byte, 57), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_57 short", @@ -1451,7 +1451,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_57], data: make([]byte, 56), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_57", @@ -1467,7 +1467,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_57], data: make([]byte, 58), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_58 short", @@ -1475,7 +1475,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_58], data: make([]byte, 57), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_58", @@ -1491,7 +1491,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_58], data: make([]byte, 59), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_59 short", @@ -1499,7 +1499,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_59], data: make([]byte, 58), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_59", @@ -1515,7 +1515,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_59], data: make([]byte, 60), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_60 short", @@ -1523,7 +1523,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_60], data: make([]byte, 59), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_60", @@ -1539,7 +1539,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_60], data: make([]byte, 61), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_61 short", @@ -1547,7 +1547,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_61], data: make([]byte, 60), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_61", @@ -1563,7 +1563,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_61], data: make([]byte, 62), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_62 short", @@ -1571,7 +1571,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_62], data: make([]byte, 61), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_62", @@ -1587,7 +1587,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_62], data: make([]byte, 63), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_63 short", @@ -1595,7 +1595,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_63], data: make([]byte, 62), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_63", @@ -1611,7 +1611,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_63], data: make([]byte, 64), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_64 short", @@ -1619,7 +1619,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_64], data: make([]byte, 63), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_64", @@ -1635,7 +1635,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_64], data: make([]byte, 65), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_65 short", @@ -1643,7 +1643,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_65], data: make([]byte, 64), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_65", @@ -1659,7 +1659,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_65], data: make([]byte, 66), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_66 short", @@ -1667,7 +1667,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_66], data: make([]byte, 65), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_66", @@ -1683,7 +1683,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_66], data: make([]byte, 67), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_67 short", @@ -1691,7 +1691,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_67], data: make([]byte, 66), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_67", @@ -1707,7 +1707,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_67], data: make([]byte, 68), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_68 short", @@ -1715,7 +1715,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_68], data: make([]byte, 67), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_68", @@ -1731,7 +1731,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_68], data: make([]byte, 69), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_69 short", @@ -1739,7 +1739,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_69], data: make([]byte, 68), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_69", @@ -1755,7 +1755,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_69], data: make([]byte, 70), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_70 short", @@ -1763,7 +1763,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_70], data: make([]byte, 69), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_70", @@ -1779,7 +1779,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_70], data: make([]byte, 71), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_71 short", @@ -1787,7 +1787,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_71], data: make([]byte, 70), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_71", @@ -1803,7 +1803,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_71], data: make([]byte, 72), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_72 short", @@ -1811,7 +1811,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_72], data: make([]byte, 71), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_72", @@ -1827,7 +1827,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_72], data: make([]byte, 73), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_73 short", @@ -1835,7 +1835,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_73], data: make([]byte, 72), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_73", @@ -1851,7 +1851,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_73], data: make([]byte, 74), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_74 short", @@ -1859,7 +1859,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_74], data: make([]byte, 73), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_74", @@ -1875,7 +1875,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_74], data: make([]byte, 75), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_75 short", @@ -1883,7 +1883,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_75], data: make([]byte, 74), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DATA_75", @@ -1899,7 +1899,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DATA_75], data: make([]byte, 76), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_PUSHDATA1", @@ -1939,7 +1939,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_1NEGATE], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_RESERVED", @@ -1955,7 +1955,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_RESERVED], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_TRUE", @@ -1971,7 +1971,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_TRUE], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_2", @@ -1987,7 +1987,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_2], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_2", @@ -2003,7 +2003,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_2], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_3", @@ -2019,7 +2019,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_3], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_4", @@ -2035,7 +2035,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_4], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_5", @@ -2051,7 +2051,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_5], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_6", @@ -2067,7 +2067,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_6], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_7", @@ -2083,7 +2083,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_7], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_8", @@ -2099,7 +2099,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_8], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_9", @@ -2115,7 +2115,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_9], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_10", @@ -2131,7 +2131,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_10], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_11", @@ -2147,7 +2147,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_11], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_12", @@ -2163,7 +2163,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_12], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_13", @@ -2179,7 +2179,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_13], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_14", @@ -2195,7 +2195,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_14], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_15", @@ -2211,7 +2211,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_15], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_16", @@ -2227,7 +2227,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_16], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_NOP", @@ -2243,7 +2243,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_NOP], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_VER", @@ -2259,7 +2259,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_VER], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_IF", @@ -2275,7 +2275,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_IF], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_NOTIF", @@ -2291,7 +2291,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_NOTIF], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_VERIF", @@ -2307,7 +2307,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_VERIF], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_VERNOTIF", @@ -2323,7 +2323,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_VERNOTIF], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_ELSE", @@ -2339,7 +2339,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_ELSE], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_ENDIF", @@ -2355,7 +2355,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_ENDIF], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_VERIFY", @@ -2371,7 +2371,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_VERIFY], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_RETURN", @@ -2387,7 +2387,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_RETURN], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_TOALTSTACK", @@ -2403,7 +2403,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_TOALTSTACK], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_FROMALTSTACK", @@ -2419,7 +2419,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_FROMALTSTACK], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_2DROP", @@ -2435,7 +2435,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_2DROP], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_2DUP", @@ -2451,7 +2451,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_2DUP], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_3DUP", @@ -2467,7 +2467,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_3DUP], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_2OVER", @@ -2483,7 +2483,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_2OVER], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_2ROT", @@ -2499,7 +2499,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_2ROT], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_2SWAP", @@ -2515,7 +2515,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_2SWAP], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_IFDUP", @@ -2531,7 +2531,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_IFDUP], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DEPTH", @@ -2547,7 +2547,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DEPTH], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DROP", @@ -2563,7 +2563,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DROP], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DUP", @@ -2579,7 +2579,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DUP], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_NIP", @@ -2595,7 +2595,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_NIP], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_OVER", @@ -2611,7 +2611,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_OVER], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_PICK", @@ -2627,7 +2627,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_PICK], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_ROLL", @@ -2643,7 +2643,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_ROLL], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_ROT", @@ -2659,7 +2659,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_ROT], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_SWAP", @@ -2675,7 +2675,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_SWAP], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_TUCK", @@ -2691,7 +2691,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_TUCK], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_CAT", @@ -2707,7 +2707,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_CAT], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_SUBSTR", @@ -2723,7 +2723,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_SUBSTR], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_LEFT", @@ -2739,7 +2739,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_LEFT], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_LEFT", @@ -2755,7 +2755,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_LEFT], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_RIGHT", @@ -2771,7 +2771,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_RIGHT], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_SIZE", @@ -2787,7 +2787,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_SIZE], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_INVERT", @@ -2803,7 +2803,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_INVERT], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_AND", @@ -2819,7 +2819,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_AND], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_OR", @@ -2835,7 +2835,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_OR], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_XOR", @@ -2851,7 +2851,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_XOR], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_EQUAL", @@ -2867,7 +2867,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_EQUAL], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_EQUALVERIFY", @@ -2883,7 +2883,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_EQUALVERIFY], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_RESERVED1", @@ -2899,7 +2899,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_RESERVED1], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_RESERVED2", @@ -2915,7 +2915,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_RESERVED2], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_1ADD", @@ -2931,7 +2931,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_1ADD], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_1SUB", @@ -2947,7 +2947,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_1SUB], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_2MUL", @@ -2963,7 +2963,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_2MUL], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_2DIV", @@ -2979,7 +2979,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_2DIV], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_NEGATE", @@ -2995,7 +2995,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_NEGATE], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_ABS", @@ -3011,7 +3011,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_ABS], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_NOT", @@ -3027,7 +3027,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_NOT], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_0NOTEQUAL", @@ -3043,7 +3043,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_0NOTEQUAL], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_ADD", @@ -3059,7 +3059,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_ADD], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_SUB", @@ -3075,7 +3075,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_SUB], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_MUL", @@ -3091,7 +3091,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_MUL], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_DIV", @@ -3107,7 +3107,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_DIV], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_MOD", @@ -3123,7 +3123,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_MOD], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_LSHIFT", @@ -3139,7 +3139,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_LSHIFT], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_RSHIFT", @@ -3155,7 +3155,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_RSHIFT], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_BOOLAND", @@ -3171,7 +3171,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_BOOLAND], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_BOOLOR", @@ -3187,7 +3187,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_BOOLOR], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_NUMEQUAL", @@ -3203,7 +3203,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_NUMEQUAL], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_NUMEQUALVERIFY", @@ -3219,7 +3219,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_NUMEQUALVERIFY], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_NUMNOTEQUAL", @@ -3235,7 +3235,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_NUMNOTEQUAL], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_LESSTHAN", @@ -3251,7 +3251,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_LESSTHAN], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_GREATERTHAN", @@ -3267,7 +3267,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_GREATERTHAN], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_LESSTHANOREQUAL", @@ -3283,7 +3283,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_LESSTHANOREQUAL], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_GREATERTHANOREQUAL", @@ -3299,7 +3299,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_GREATERTHANOREQUAL], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_MIN", @@ -3315,7 +3315,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_MIN], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_MAX", @@ -3331,7 +3331,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_MAX], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_WITHIN", @@ -3347,7 +3347,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_WITHIN], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_RIPEMD160", @@ -3363,7 +3363,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_RIPEMD160], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_SHA1", @@ -3379,7 +3379,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_SHA1], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_SHA256", @@ -3395,7 +3395,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_SHA256], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_HASH160", @@ -3411,7 +3411,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_HASH160], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_HASH256", @@ -3427,7 +3427,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_HASH256], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_CODESAPERATOR", @@ -3443,7 +3443,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_CODESEPARATOR], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_CHECKSIG", @@ -3459,7 +3459,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_CHECKSIG], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_CHECKSIGVERIFY", @@ -3475,7 +3475,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_CHECKSIGVERIFY], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_CHECKMULTISIG", @@ -3491,7 +3491,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_CHECKMULTISIG], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_CHECKMULTISIGVERIFY", @@ -3507,7 +3507,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_CHECKMULTISIGVERIFY], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_NOP1", @@ -3523,7 +3523,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_NOP1], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_NOP2", @@ -3539,7 +3539,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_NOP2], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_NOP3", @@ -3555,7 +3555,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_NOP3], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_NOP4", @@ -3571,7 +3571,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_NOP4], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_NOP5", @@ -3587,7 +3587,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_NOP5], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_NOP6", @@ -3603,7 +3603,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_NOP6], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_NOP7", @@ -3619,7 +3619,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_NOP7], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_NOP8", @@ -3635,7 +3635,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_NOP8], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_NOP9", @@ -3651,7 +3651,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_NOP9], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_NOP10", @@ -3667,7 +3667,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_NOP10], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_PUBKEYHASH", @@ -3683,7 +3683,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_PUBKEYHASH], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_PUBKEY", @@ -3699,7 +3699,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_PUBKEY], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, { name: "OP_INVALIDOPCODE", @@ -3715,7 +3715,7 @@ var popTests = []popTest{ opcode: opcodemapPreinit[OP_INVALIDOPCODE], data: make([]byte, 1), }, - expectedErr: StackErrInvalidOpcode, + expectedErr: ErrStackInvalidOpcode, }, } diff --git a/opcode.go b/opcode.go index 4fb85dd8..aa983b0a 100644 --- a/opcode.go +++ b/opcode.go @@ -939,23 +939,23 @@ func (pop *parsedOpcode) conditional() bool { func (pop *parsedOpcode) exec(s *Script) error { // Disabled opcodes are ``fail on program counter''. if pop.disabled() { - return StackErrOpDisabled + return ErrStackOpDisabled } // Always-illegal opcodes are ``fail on program counter''. if pop.alwaysIllegal() { - return StackErrReservedOpcode + return ErrStackReservedOpcode } // Note that this includes OP_RESERVED which counts as a push operation. if pop.opcode.value > OP_16 { s.numOps++ if s.numOps > MaxOpsPerScript { - return StackErrTooManyOperations + return ErrStackTooManyOperations } } else if len(pop.data) > MaxScriptElementSize { - return StackErrElementTooBig + return ErrStackElementTooBig } // If we are not a conditional opcode and we aren't executing, then @@ -1012,7 +1012,7 @@ func (pop *parsedOpcode) bytes() ([]byte, error) { retbytes[0] = pop.opcode.value if pop.opcode.length == 1 { if len(pop.data) != 0 { - return nil, StackErrInvalidOpcode + return nil, ErrStackInvalidOpcode } return retbytes, nil } @@ -1041,7 +1041,7 @@ func (pop *parsedOpcode) bytes() ([]byte, error) { retbytes = append(retbytes, pop.data...) if len(retbytes) != nbytes { - return nil, StackErrInvalidOpcode + return nil, ErrStackInvalidOpcode } return retbytes, nil @@ -1050,16 +1050,16 @@ func (pop *parsedOpcode) bytes() ([]byte, error) { // opcode implementation functions from here func opcodeDisabled(op *parsedOpcode, s *Script) error { - return StackErrOpDisabled + return ErrStackOpDisabled } func opcodeReserved(op *parsedOpcode, s *Script) error { - return StackErrReservedOpcode + return ErrStackReservedOpcode } // Recognised opcode, but for bitcoind internal use only. func opcodeInvalid(op *parsedOpcode, s *Script) error { - return StackErrInvalidOpcode + return ErrStackInvalidOpcode } func opcodeFalse(op *parsedOpcode, s *Script) error { @@ -1141,7 +1141,7 @@ func opcodeNotIf(op *parsedOpcode, s *Script) error { func opcodeElse(op *parsedOpcode, s *Script) error { if len(s.condStack) < 2 { // intial true cannot be toggled, only pushed conditionals - return StackErrNoIf + return ErrStackNoIf } switch s.condStack[0] { @@ -1160,7 +1160,7 @@ func opcodeElse(op *parsedOpcode, s *Script) error { func opcodeEndif(op *parsedOpcode, s *Script) error { if len(s.condStack) < 2 { // intial true cannot be popped, only pushed conditionals - return StackErrNoIf + return ErrStackNoIf } stk := make([]int, len(s.condStack)-1, len(s.condStack)-1) @@ -1176,13 +1176,13 @@ func opcodeVerify(op *parsedOpcode, s *Script) error { } if verified != true { - return StackErrVerifyFailed + return ErrStackVerifyFailed } return nil } func opcodeReturn(op *parsedOpcode, s *Script) error { - return StackErrEarlyReturn + return ErrStackEarlyReturn } func opcodeToAltStack(op *parsedOpcode, s *Script) error { @@ -1839,16 +1839,16 @@ func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error { } // XXX arbitrary limits - // nore more than 20 pubkeyhs, or 201 operations + // nore more than 20 pubkeys, or 201 operations // PopInt promises that the int returned is 32 bit. npk := int(numPubkeys.Int64()) if npk < 0 || npk > MaxPubKeysPerMultiSig { - return StackErrTooManyPubkeys + return ErrStackTooManyPubkeys } s.numOps += npk if s.numOps > MaxOpsPerScript { - return StackErrTooManyOperations + return ErrStackTooManyOperations } pubKeyStrings := make([][]byte, npk) pubKeys := make([]*btcec.PublicKey, npk) diff --git a/opcode_test.go b/opcode_test.go index 0d95e571..6bed4c31 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -363,15 +363,15 @@ var opcodeTests = []opcodeTest{ {script: []byte{btcscript.OP_1, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: false}, {script: []byte{btcscript.OP_1, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: true}, {script: []byte{btcscript.OP_0, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: false}, - {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2}, shouldFail: btcscript.StackErrMissingEndif}, - {script: []byte{btcscript.OP_1, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2}, shouldFail: btcscript.StackErrMissingEndif}, + {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2}, shouldFail: btcscript.ErrStackMissingEndif}, + {script: []byte{btcscript.OP_1, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2}, shouldFail: btcscript.ErrStackMissingEndif}, {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_IF, btcscript.OP_IF, btcscript.OP_1, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ENDIF}, shouldPass: true}, - {script: []byte{btcscript.OP_1, btcscript.OP_IF, btcscript.OP_IF, btcscript.OP_1, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ENDIF}, shouldFail: btcscript.StackErrUnderflow}, + {script: []byte{btcscript.OP_1, btcscript.OP_IF, btcscript.OP_IF, btcscript.OP_1, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ENDIF}, shouldFail: btcscript.ErrStackUnderflow}, {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ELSE, btcscript.OP_1, btcscript.OP_ENDIF}, shouldPass: true}, {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ELSE, btcscript.OP_1, btcscript.OP_ENDIF}, shouldPass: true}, - {script: []byte{btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ENDIF}, shouldFail: btcscript.StackErrUnderflow}, - {script: []byte{btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF}, shouldFail: btcscript.StackErrNoIf}, - {script: []byte{btcscript.OP_ENDIF}, shouldFail: btcscript.StackErrNoIf}, + {script: []byte{btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ENDIF}, shouldFail: btcscript.ErrStackUnderflow}, + {script: []byte{btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF}, shouldFail: btcscript.ErrStackNoIf}, + {script: []byte{btcscript.OP_ENDIF}, shouldFail: btcscript.ErrStackNoIf}, /* up here because error from sig parsing is undefined. */ {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_DATA_65, 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, @@ -586,7 +586,7 @@ var detailedTests = []detailedTest{ name: "dup too much", before: [][]byte{}, script: []byte{btcscript.OP_DUP}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, after: [][]byte{}, disassembly: "OP_DUP", }, @@ -594,7 +594,7 @@ var detailedTests = []detailedTest{ name: "2dup too much", before: [][]byte{{1}}, script: []byte{btcscript.OP_2DUP}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, after: [][]byte{}, disassembly: "OP_2DUP", }, @@ -602,7 +602,7 @@ var detailedTests = []detailedTest{ name: "2dup way too much", before: [][]byte{}, script: []byte{btcscript.OP_2DUP}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, after: [][]byte{}, disassembly: "OP_2DUP", }, @@ -610,7 +610,7 @@ var detailedTests = []detailedTest{ name: "3dup too much", before: [][]byte{{1}, {2}}, script: []byte{btcscript.OP_3DUP}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, after: [][]byte{}, disassembly: "OP_3DUP", }, @@ -618,7 +618,7 @@ var detailedTests = []detailedTest{ name: "3dup kinda too much", before: [][]byte{{1}}, script: []byte{btcscript.OP_3DUP}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, after: [][]byte{}, disassembly: "OP_3DUP", }, @@ -626,7 +626,7 @@ var detailedTests = []detailedTest{ name: "3dup way too much", before: [][]byte{}, script: []byte{btcscript.OP_3DUP}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, after: [][]byte{}, disassembly: "OP_3DUP", }, @@ -641,7 +641,7 @@ var detailedTests = []detailedTest{ name: "Nip too much", before: [][]byte{{1}}, script: []byte{btcscript.OP_NIP}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, after: [][]byte{{2}, {3}}, disassembly: "OP_NIP", }, @@ -656,7 +656,7 @@ var detailedTests = []detailedTest{ name: "a little tucked up", before: [][]byte{{1}}, // too few arguments for tuck script: []byte{btcscript.OP_TUCK}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, after: [][]byte{}, disassembly: "OP_TUCK", }, @@ -664,7 +664,7 @@ var detailedTests = []detailedTest{ name: "all tucked up", before: [][]byte{}, // too few arguments for tuck script: []byte{btcscript.OP_TUCK}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_TUCK", }, { @@ -685,21 +685,21 @@ var detailedTests = []detailedTest{ name: "drop too much", before: [][]byte{}, script: []byte{btcscript.OP_DROP}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_DROP", }, { name: "2drop too much", before: [][]byte{{1}}, script: []byte{btcscript.OP_2DROP}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_2DROP", }, { name: "2drop far too much", before: [][]byte{}, script: []byte{btcscript.OP_2DROP}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_2DROP", }, { @@ -720,7 +720,7 @@ var detailedTests = []detailedTest{ name: "Rot too little", before: [][]byte{{1}, {2}}, script: []byte{btcscript.OP_ROT}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_ROT", }, { @@ -741,7 +741,7 @@ var detailedTests = []detailedTest{ name: "Swap too little", before: [][]byte{{1}}, script: []byte{btcscript.OP_SWAP}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_SWAP", }, { @@ -762,7 +762,7 @@ var detailedTests = []detailedTest{ name: "Over too little", before: [][]byte{{1}}, script: []byte{btcscript.OP_OVER}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_OVER", }, { @@ -783,28 +783,28 @@ var detailedTests = []detailedTest{ name: "Pick too little", before: [][]byte{{1}, {1}}, script: []byte{btcscript.OP_PICK}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_PICK", }, { name: "Pick nothing", before: [][]byte{{}}, script: []byte{btcscript.OP_PICK}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_PICK", }, { name: "Pick no args", before: [][]byte{}, script: []byte{btcscript.OP_PICK}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_PICK", }, { name: "Pick stupid numbers", before: [][]byte{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, script: []byte{btcscript.OP_PICK}, - expectedReturn: btcscript.StackErrNumberTooBig, + expectedReturn: btcscript.ErrStackNumberTooBig, disassembly: "OP_PICK", }, { @@ -825,28 +825,28 @@ var detailedTests = []detailedTest{ name: "Roll too little", before: [][]byte{{1}, {1}}, script: []byte{btcscript.OP_ROLL}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_ROLL", }, { name: "Roll nothing ", before: [][]byte{{1}}, script: []byte{btcscript.OP_ROLL}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_ROLL", }, { name: "Roll no args ", before: [][]byte{}, script: []byte{btcscript.OP_ROLL}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_ROLL", }, { name: "Roll stupid numbers", before: [][]byte{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, script: []byte{btcscript.OP_ROLL}, - expectedReturn: btcscript.StackErrNumberTooBig, + expectedReturn: btcscript.ErrStackNumberTooBig, disassembly: "OP_ROLL", }, { @@ -867,7 +867,7 @@ var detailedTests = []detailedTest{ name: "ifdup (empty)", before: [][]byte{}, script: []byte{btcscript.OP_IFDUP}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, after: [][]byte{{0}}, disassembly: "OP_IFDUP", }, @@ -886,7 +886,7 @@ var detailedTests = []detailedTest{ before: [][]byte{}, altbefore: [][]byte{}, script: []byte{btcscript.OP_TOALTSTACK}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_TOALTSTACK", }, { @@ -903,7 +903,7 @@ var detailedTests = []detailedTest{ before: [][]byte{}, altbefore: [][]byte{}, script: []byte{btcscript.OP_FROMALTSTACK}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_FROMALTSTACK", }, { @@ -932,7 +932,7 @@ var detailedTests = []detailedTest{ name: "op_size (invalid)", before: [][]byte{}, script: []byte{btcscript.OP_SIZE}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_SIZE", }, { @@ -953,7 +953,7 @@ var detailedTests = []detailedTest{ name: "OP_EQUAL (one arg)", before: [][]byte{{1, 2, 3, 4}}, script: []byte{btcscript.OP_EQUAL}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, after: [][]byte{{0}}, disassembly: "OP_EQUAL", }, @@ -961,7 +961,7 @@ var detailedTests = []detailedTest{ name: "OP_EQUAL (no arg)", before: [][]byte{}, script: []byte{btcscript.OP_EQUAL}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, after: [][]byte{{0}}, disassembly: "OP_EQUAL", }, @@ -976,7 +976,7 @@ var detailedTests = []detailedTest{ name: "OP_EQUALVERIFY (invalid)", before: [][]byte{{1, 2, 3, 4}, {1, 2, 3, 3}}, script: []byte{btcscript.OP_EQUALVERIFY}, - expectedReturn: btcscript.StackErrVerifyFailed, + expectedReturn: btcscript.ErrStackVerifyFailed, after: [][]byte{}, disassembly: "OP_EQUALVERIFY", }, @@ -984,14 +984,14 @@ var detailedTests = []detailedTest{ name: "OP_EQUALVERIFY (one arg)", before: [][]byte{{1, 2, 3, 4}}, script: []byte{btcscript.OP_EQUALVERIFY}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_EQUALVERIFY", }, { name: "OP_EQUALVERIFY (no arg)", before: [][]byte{}, script: []byte{btcscript.OP_EQUALVERIFY}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_EQUALVERIFY", }, { @@ -1026,7 +1026,7 @@ var detailedTests = []detailedTest{ name: "OP_ABS (empty)", before: [][]byte{}, script: []byte{btcscript.OP_ABS}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_ABS", }, { @@ -1960,8 +1960,8 @@ var detailedTests = []detailedTest{ name: "op_data too short", before: [][]byte{}, script: []byte{btcscript.OP_DATA_2, 1}, - expectedReturn: btcscript.StackErrShortScript, - disassemblyerr: btcscript.StackErrShortScript, + expectedReturn: btcscript.ErrStackShortScript, + disassemblyerr: btcscript.ErrStackShortScript, }, { name: "op_pushdata_1", @@ -1973,8 +1973,8 @@ var detailedTests = []detailedTest{ { name: "op_pushdata_1 too short", script: []byte{btcscript.OP_PUSHDATA1, 1}, - expectedReturn: btcscript.StackErrShortScript, - disassemblyerr: btcscript.StackErrShortScript, + expectedReturn: btcscript.ErrStackShortScript, + disassemblyerr: btcscript.ErrStackShortScript, }, { name: "op_pushdata_2", @@ -1986,8 +1986,8 @@ var detailedTests = []detailedTest{ { name: "op_pushdata_2 too short", script: []byte{btcscript.OP_PUSHDATA2, 2, 0}, - expectedReturn: btcscript.StackErrShortScript, - disassemblyerr: btcscript.StackErrShortScript, + expectedReturn: btcscript.ErrStackShortScript, + disassemblyerr: btcscript.ErrStackShortScript, }, { name: "op_pushdata_4", @@ -1999,8 +1999,8 @@ var detailedTests = []detailedTest{ { name: "op_pushdata_4 too short", script: []byte{btcscript.OP_PUSHDATA4, 4, 0, 0, 0}, - expectedReturn: btcscript.StackErrShortScript, - disassemblyerr: btcscript.StackErrShortScript, + expectedReturn: btcscript.ErrStackShortScript, + disassemblyerr: btcscript.ErrStackShortScript, }, // XXX also pushdata cases where the pushed data isn't long enough, // no real error type defined for that as of yet. @@ -2009,7 +2009,7 @@ var detailedTests = []detailedTest{ name: "OP_SHA1 no args", before: [][]byte{}, script: []byte{btcscript.OP_SHA1}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_SHA1", }, { @@ -2025,14 +2025,14 @@ var detailedTests = []detailedTest{ name: "OP_SHA256 no args", before: [][]byte{}, script: []byte{btcscript.OP_SHA256}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_SHA256", }, { name: "OP_RIPEMD160 no args", before: [][]byte{}, script: []byte{btcscript.OP_RIPEMD160}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_RIPEMD160", }, // data taken from transaction @@ -2097,7 +2097,7 @@ var detailedTests = []detailedTest{ { name: "op_hash160 no args", script: []byte{btcscript.OP_HASH160}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_HASH160", }, // hash256 test taken from spend of: @@ -2123,7 +2123,7 @@ var detailedTests = []detailedTest{ { name: "OP_HASH256 no args", script: []byte{btcscript.OP_HASH256}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_HASH256", }, // We need a more involved setup to test OP_CHECKSIG and @@ -2132,7 +2132,7 @@ var detailedTests = []detailedTest{ { name: "OP_CHECKSIG one arg", script: []byte{btcscript.OP_1, btcscript.OP_CHECKSIG}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "1 OP_CHECKSIG", nSigOps: 1, nPreciseSigOps: 1, @@ -2140,7 +2140,7 @@ var detailedTests = []detailedTest{ { name: "OP_CHECKSIG no arg", script: []byte{btcscript.OP_CHECKSIG}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_CHECKSIG", nSigOps: 1, nPreciseSigOps: 1, @@ -2149,7 +2149,7 @@ var detailedTests = []detailedTest{ name: "OP_CHECKSIGVERIFY one arg", script: []byte{btcscript.OP_1, btcscript.OP_CHECKSIGVERIFY}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "1 OP_CHECKSIGVERIFY", nSigOps: 1, nPreciseSigOps: 1, @@ -2157,7 +2157,7 @@ var detailedTests = []detailedTest{ { name: "OP_CHECKSIGVERIFY no arg", script: []byte{btcscript.OP_CHECKSIGVERIFY}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_CHECKSIGVERIFY", nSigOps: 1, nPreciseSigOps: 1, @@ -2165,7 +2165,7 @@ var detailedTests = []detailedTest{ { name: "OP_CHECKMULTISIG no args", script: []byte{btcscript.OP_CHECKMULTISIG}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 20, @@ -2175,7 +2175,7 @@ var detailedTests = []detailedTest{ script: []byte{btcscript.OP_PUSHDATA1, 0x9, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, btcscript.OP_CHECKMULTISIG}, - expectedReturn: btcscript.StackErrNumberTooBig, + expectedReturn: btcscript.ErrStackNumberTooBig, disassembly: "010203040506070809 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 20, @@ -2184,7 +2184,7 @@ var detailedTests = []detailedTest{ name: "OP_CHECKMULTISIG too many keys", script: []byte{btcscript.OP_DATA_1, 21, btcscript.OP_CHECKMULTISIG}, - expectedReturn: btcscript.StackErrTooManyPubkeys, + expectedReturn: btcscript.ErrStackTooManyPubkeys, disassembly: "15 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 20, @@ -2193,7 +2193,7 @@ var detailedTests = []detailedTest{ name: "OP_CHECKMULTISIG lying about pubkeys", script: []byte{btcscript.OP_1, btcscript.OP_CHECKMULTISIG}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "1 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 1, @@ -2213,7 +2213,7 @@ var detailedTests = []detailedTest{ 0xd8, 0x4c, btcscript.OP_1, btcscript.OP_CHECKMULTISIG}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c 1 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 1, @@ -2235,7 +2235,7 @@ var detailedTests = []detailedTest{ 0xd8, 0x4c, btcscript.OP_1, btcscript.OP_CHECKMULTISIG}, - expectedReturn: btcscript.StackErrNumberTooBig, + expectedReturn: btcscript.ErrStackNumberTooBig, disassembly: "010203040506070809 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c 1 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 1, @@ -2254,7 +2254,7 @@ var detailedTests = []detailedTest{ 0xd8, 0x4c, btcscript.OP_1, btcscript.OP_CHECKMULTISIG}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c 1 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 1, @@ -2317,7 +2317,7 @@ var detailedTests = []detailedTest{ { name: "OP_CHECKMULTISIGVERIFY no args", script: []byte{btcscript.OP_CHECKMULTISIGVERIFY}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "OP_CHECKMULTISIGVERIFY", nSigOps: 20, nPreciseSigOps: 20, @@ -2327,7 +2327,7 @@ var detailedTests = []detailedTest{ script: []byte{btcscript.OP_PUSHDATA1, 0x9, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, btcscript.OP_CHECKMULTISIGVERIFY}, - expectedReturn: btcscript.StackErrNumberTooBig, + expectedReturn: btcscript.ErrStackNumberTooBig, disassembly: "010203040506070809 OP_CHECKMULTISIGVERIFY", nSigOps: 20, nPreciseSigOps: 20, @@ -2336,7 +2336,7 @@ var detailedTests = []detailedTest{ name: "OP_CHECKMULTISIGVERIFY too many keys", script: []byte{btcscript.OP_DATA_1, 21, btcscript.OP_CHECKMULTISIGVERIFY}, - expectedReturn: btcscript.StackErrTooManyPubkeys, + expectedReturn: btcscript.ErrStackTooManyPubkeys, disassembly: "15 OP_CHECKMULTISIGVERIFY", nSigOps: 20, nPreciseSigOps: 20, @@ -2345,7 +2345,7 @@ var detailedTests = []detailedTest{ name: "OP_CHECKMULTISIGVERIFY lying about pubkeys", script: []byte{btcscript.OP_1, btcscript.OP_CHECKMULTISIGVERIFY}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "1 OP_CHECKMULTISIGVERIFY", nSigOps: 20, nPreciseSigOps: 1, @@ -2365,7 +2365,7 @@ var detailedTests = []detailedTest{ 0xd8, 0x4c, btcscript.OP_1, btcscript.OP_CHECKMULTISIGVERIFY}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c 1 OP_CHECKMULTISIGVERIFY", nSigOps: 20, nPreciseSigOps: 1, @@ -2386,7 +2386,7 @@ var detailedTests = []detailedTest{ 0xd8, 0x4c, btcscript.OP_1, btcscript.OP_CHECKMULTISIGVERIFY}, - expectedReturn: btcscript.StackErrNumberTooBig, + expectedReturn: btcscript.ErrStackNumberTooBig, disassembly: "010203040506070809 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c 1 OP_CHECKMULTISIGVERIFY", nSigOps: 20, nPreciseSigOps: 1, @@ -2405,7 +2405,7 @@ var detailedTests = []detailedTest{ 0xd8, 0x4c, btcscript.OP_1, btcscript.OP_CHECKMULTISIGVERIFY}, - expectedReturn: btcscript.StackErrUnderflow, + expectedReturn: btcscript.ErrStackUnderflow, disassembly: "1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c 1 OP_CHECKMULTISIGVERIFY", nSigOps: 20, nPreciseSigOps: 1, @@ -2435,7 +2435,7 @@ var detailedTests = []detailedTest{ 0xd8, 0x4c, btcscript.OP_1, btcscript.OP_CHECKMULTISIGVERIFY}, - expectedReturn: btcscript.StackErrVerifyFailed, + expectedReturn: btcscript.ErrStackVerifyFailed, disassembly: "1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c 1 OP_CHECKMULTISIGVERIFY", nSigOps: 20, nPreciseSigOps: 1, @@ -2458,7 +2458,7 @@ var detailedTests = []detailedTest{ btcscript.OP_1, btcscript.OP_1, btcscript.OP_1, btcscript.OP_CHECKMULTISIGVERIFY}, - expectedReturn: btcscript.StackErrVerifyFailed, + expectedReturn: btcscript.ErrStackVerifyFailed, disassembly: "1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 1 1 1 OP_CHECKMULTISIGVERIFY", nSigOps: 20, nPreciseSigOps: 1, @@ -2879,7 +2879,7 @@ var detailedTests = []detailedTest{ btcscript.OP_DUP, btcscript.OP_DROP, }, - expectedReturn: btcscript.StackErrTooManyOperations, + expectedReturn: btcscript.ErrStackTooManyOperations, disassembly: "1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP", }, { @@ -3093,7 +3093,7 @@ var detailedTests = []detailedTest{ btcscript.OP_2, btcscript.OP_CHECKMULTISIG, }, - expectedReturn: btcscript.StackErrTooManyOperations, + expectedReturn: btcscript.ErrStackTooManyOperations, disassembly: "1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP 1 1 1 1 2 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 2, @@ -3284,544 +3284,544 @@ var detailedTests = []detailedTest{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, - expectedReturn: btcscript.StackErrElementTooBig, + expectedReturn: btcscript.ErrStackElementTooBig, // element too big is a parse error. disassembly: "0102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708", }, { name: "OP_CAT disabled", script: []byte{btcscript.OP_CAT}, - expectedReturn: btcscript.StackErrOpDisabled, + expectedReturn: btcscript.ErrStackOpDisabled, disassembly: "OP_CAT", }, { name: "OP_SUBSTR disabled", script: []byte{btcscript.OP_SUBSTR}, - expectedReturn: btcscript.StackErrOpDisabled, + expectedReturn: btcscript.ErrStackOpDisabled, disassembly: "OP_SUBSTR", }, { name: "OP_LEFT disabled", script: []byte{btcscript.OP_LEFT}, - expectedReturn: btcscript.StackErrOpDisabled, + expectedReturn: btcscript.ErrStackOpDisabled, disassembly: "OP_LEFT", }, { name: "OP_RIGHT disabled", script: []byte{btcscript.OP_RIGHT}, - expectedReturn: btcscript.StackErrOpDisabled, + expectedReturn: btcscript.ErrStackOpDisabled, disassembly: "OP_RIGHT", }, { name: "OP_INVERT disabled", script: []byte{btcscript.OP_INVERT}, - expectedReturn: btcscript.StackErrOpDisabled, + expectedReturn: btcscript.ErrStackOpDisabled, disassembly: "OP_INVERT", }, { name: "OP_AND disabled", script: []byte{btcscript.OP_AND}, - expectedReturn: btcscript.StackErrOpDisabled, + expectedReturn: btcscript.ErrStackOpDisabled, disassembly: "OP_AND", }, { name: "OP_OR disabled", script: []byte{btcscript.OP_OR}, - expectedReturn: btcscript.StackErrOpDisabled, + expectedReturn: btcscript.ErrStackOpDisabled, disassembly: "OP_OR", }, { name: "OP_XOR disabled", script: []byte{btcscript.OP_XOR}, - expectedReturn: btcscript.StackErrOpDisabled, + expectedReturn: btcscript.ErrStackOpDisabled, disassembly: "OP_XOR", }, { name: "OP_2MUL disabled", script: []byte{btcscript.OP_2MUL}, - expectedReturn: btcscript.StackErrOpDisabled, + expectedReturn: btcscript.ErrStackOpDisabled, disassembly: "OP_2MUL", }, { name: "OP_2DIV disabled", script: []byte{btcscript.OP_2DIV}, - expectedReturn: btcscript.StackErrOpDisabled, + expectedReturn: btcscript.ErrStackOpDisabled, disassembly: "OP_2DIV", }, { name: "OP_2DIV disabled", script: []byte{btcscript.OP_2DIV}, - expectedReturn: btcscript.StackErrOpDisabled, + expectedReturn: btcscript.ErrStackOpDisabled, disassembly: "OP_2DIV", }, { name: "OP_MUL disabled", script: []byte{btcscript.OP_MUL}, - expectedReturn: btcscript.StackErrOpDisabled, + expectedReturn: btcscript.ErrStackOpDisabled, disassembly: "OP_MUL", }, { name: "OP_DIV disabled", script: []byte{btcscript.OP_DIV}, - expectedReturn: btcscript.StackErrOpDisabled, + expectedReturn: btcscript.ErrStackOpDisabled, disassembly: "OP_DIV", }, { name: "OP_MOD disabled", script: []byte{btcscript.OP_MOD}, - expectedReturn: btcscript.StackErrOpDisabled, + expectedReturn: btcscript.ErrStackOpDisabled, disassembly: "OP_MOD", }, { name: "OP_LSHIFT disabled", script: []byte{btcscript.OP_LSHIFT}, - expectedReturn: btcscript.StackErrOpDisabled, + expectedReturn: btcscript.ErrStackOpDisabled, disassembly: "OP_LSHIFT", }, { name: "OP_RSHIFT disabled", script: []byte{btcscript.OP_RSHIFT}, - expectedReturn: btcscript.StackErrOpDisabled, + expectedReturn: btcscript.ErrStackOpDisabled, disassembly: "OP_RSHIFT", }, // Reserved opcodes { name: "OP_RESERVED reserved", script: []byte{btcscript.OP_RESERVED}, - expectedReturn: btcscript.StackErrReservedOpcode, + expectedReturn: btcscript.ErrStackReservedOpcode, disassembly: "OP_RESERVED", }, { name: "OP_VER reserved", script: []byte{btcscript.OP_VER}, - expectedReturn: btcscript.StackErrReservedOpcode, + expectedReturn: btcscript.ErrStackReservedOpcode, disassembly: "OP_VER", }, { name: "OP_VERIF reserved", script: []byte{btcscript.OP_VERIF}, - expectedReturn: btcscript.StackErrReservedOpcode, + expectedReturn: btcscript.ErrStackReservedOpcode, disassembly: "OP_VERIF", }, { name: "OP_VERNOTIF reserved", script: []byte{btcscript.OP_VERNOTIF}, - expectedReturn: btcscript.StackErrReservedOpcode, + expectedReturn: btcscript.ErrStackReservedOpcode, disassembly: "OP_VERNOTIF", }, { name: "OP_RESERVED1 reserved", script: []byte{btcscript.OP_RESERVED1}, - expectedReturn: btcscript.StackErrReservedOpcode, + expectedReturn: btcscript.ErrStackReservedOpcode, disassembly: "OP_RESERVED1", }, { name: "OP_RESERVED2 reserved", script: []byte{btcscript.OP_RESERVED2}, - expectedReturn: btcscript.StackErrReservedOpcode, + expectedReturn: btcscript.ErrStackReservedOpcode, disassembly: "OP_RESERVED2", }, // Invalid Opcodes { name: "invalid opcode 186", script: []byte{btcscript.OP_UNKNOWN186}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN186", }, { name: "invalid opcode 187", script: []byte{btcscript.OP_UNKNOWN187}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN187", }, { name: "invalid opcode 188", script: []byte{btcscript.OP_UNKNOWN188}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN188", }, { name: "invalid opcode 189", script: []byte{btcscript.OP_UNKNOWN189}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN189", }, { name: "invalid opcode 190", script: []byte{btcscript.OP_UNKNOWN190}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN190", }, { name: "invalid opcode 191", script: []byte{btcscript.OP_UNKNOWN191}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN191", }, { name: "invalid opcode 192", script: []byte{btcscript.OP_UNKNOWN192}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN192", }, { name: "invalid opcode 193", script: []byte{btcscript.OP_UNKNOWN193}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN193", }, { name: "invalid opcode 194", script: []byte{btcscript.OP_UNKNOWN194}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN194", }, { name: "invalid opcode 195", script: []byte{btcscript.OP_UNKNOWN195}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN195", }, { name: "invalid opcode 196", script: []byte{btcscript.OP_UNKNOWN196}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN196", }, { name: "invalid opcode 197", script: []byte{btcscript.OP_UNKNOWN197}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN197", }, { name: "invalid opcode 198", script: []byte{btcscript.OP_UNKNOWN198}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN198", }, { name: "invalid opcode 199", script: []byte{btcscript.OP_UNKNOWN199}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN199", }, { name: "invalid opcode 200", script: []byte{btcscript.OP_UNKNOWN200}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN200", }, { name: "invalid opcode 201", script: []byte{btcscript.OP_UNKNOWN201}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN201", }, { name: "invalid opcode 202", script: []byte{btcscript.OP_UNKNOWN202}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN202", }, { name: "invalid opcode 203", script: []byte{btcscript.OP_UNKNOWN203}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN203", }, { name: "invalid opcode 204", script: []byte{btcscript.OP_UNKNOWN204}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN204", }, { name: "invalid opcode 205", script: []byte{btcscript.OP_UNKNOWN205}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN205", }, { name: "invalid opcode 206", script: []byte{btcscript.OP_UNKNOWN206}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN206", }, { name: "invalid opcode 207", script: []byte{btcscript.OP_UNKNOWN207}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN207", }, { name: "invalid opcode 208", script: []byte{btcscript.OP_UNKNOWN208}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN208", }, { name: "invalid opcode 209", script: []byte{btcscript.OP_UNKNOWN209}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN209", }, { name: "invalid opcode 210", script: []byte{btcscript.OP_UNKNOWN210}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN210", }, { name: "invalid opcode 211", script: []byte{btcscript.OP_UNKNOWN211}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN211", }, { name: "invalid opcode 212", script: []byte{btcscript.OP_UNKNOWN212}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN212", }, { name: "invalid opcode 213", script: []byte{btcscript.OP_UNKNOWN213}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN213", }, { name: "invalid opcode 214", script: []byte{btcscript.OP_UNKNOWN214}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN214", }, { name: "invalid opcode 215", script: []byte{btcscript.OP_UNKNOWN215}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN215", }, { name: "invalid opcode 216", script: []byte{btcscript.OP_UNKNOWN216}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN216", }, { name: "invalid opcode 217", script: []byte{btcscript.OP_UNKNOWN217}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN217", }, { name: "invalid opcode 218", script: []byte{btcscript.OP_UNKNOWN218}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN218", }, { name: "invalid opcode 219", script: []byte{btcscript.OP_UNKNOWN219}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN219", }, { name: "invalid opcode 220", script: []byte{btcscript.OP_UNKNOWN220}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN220", }, { name: "invalid opcode 221", script: []byte{btcscript.OP_UNKNOWN221}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN221", }, { name: "invalid opcode 222", script: []byte{btcscript.OP_UNKNOWN222}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN222", }, { name: "invalid opcode 223", script: []byte{btcscript.OP_UNKNOWN223}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN223", }, { name: "invalid opcode 224", script: []byte{btcscript.OP_UNKNOWN224}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN224", }, { name: "invalid opcode 225", script: []byte{btcscript.OP_UNKNOWN225}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN225", }, { name: "invalid opcode 226", script: []byte{btcscript.OP_UNKNOWN226}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN226", }, { name: "invalid opcode 227", script: []byte{btcscript.OP_UNKNOWN227}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN227", }, { name: "invalid opcode 228", script: []byte{btcscript.OP_UNKNOWN228}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN228", }, { name: "invalid opcode 229", script: []byte{btcscript.OP_UNKNOWN229}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN229", }, { name: "invalid opcode 230", script: []byte{btcscript.OP_UNKNOWN230}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN230", }, { name: "invalid opcode 231", script: []byte{btcscript.OP_UNKNOWN231}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN231", }, { name: "invalid opcode 232", script: []byte{btcscript.OP_UNKNOWN232}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN232", }, { name: "invalid opcode 233", script: []byte{btcscript.OP_UNKNOWN233}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN233", }, { name: "invalid opcode 234", script: []byte{btcscript.OP_UNKNOWN234}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN234", }, { name: "invalid opcode 235", script: []byte{btcscript.OP_UNKNOWN235}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN235", }, { name: "invalid opcode 236", script: []byte{btcscript.OP_UNKNOWN236}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN236", }, { name: "invalid opcode 237", script: []byte{btcscript.OP_UNKNOWN237}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN237", }, { name: "invalid opcode 238", script: []byte{btcscript.OP_UNKNOWN238}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN238", }, { name: "invalid opcode 239", script: []byte{btcscript.OP_UNKNOWN239}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN239", }, { name: "invalid opcode 240", script: []byte{btcscript.OP_UNKNOWN240}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN240", }, { name: "invalid opcode 241", script: []byte{btcscript.OP_UNKNOWN241}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN241", }, { name: "invalid opcode 242", script: []byte{btcscript.OP_UNKNOWN242}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN242", }, { name: "invalid opcode 243", script: []byte{btcscript.OP_UNKNOWN243}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN243", }, { name: "invalid opcode 244", script: []byte{btcscript.OP_UNKNOWN244}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN244", }, { name: "invalid opcode 245", script: []byte{btcscript.OP_UNKNOWN245}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN245", }, { name: "invalid opcode 246", script: []byte{btcscript.OP_UNKNOWN246}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN246", }, { name: "invalid opcode 247", script: []byte{btcscript.OP_UNKNOWN247}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN247", }, { name: "invalid opcode 248", script: []byte{btcscript.OP_UNKNOWN248}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN248", }, { name: "invalid opcode 249", script: []byte{btcscript.OP_UNKNOWN249}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN249", }, { name: "invalid opcode 250", script: []byte{btcscript.OP_UNKNOWN250}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN250", }, { name: "invalid opcode 251", script: []byte{btcscript.OP_UNKNOWN251}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN251", }, { name: "invalid opcode 252", script: []byte{btcscript.OP_UNKNOWN252}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN252", }, @@ -4231,19 +4231,19 @@ var detailedTests = []detailedTest{ { name: "invalid opcode OP_PUBKEY", script: []byte{btcscript.OP_PUBKEY}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_PUBKEY", }, { name: "invalid opcode OP_PUBKEYHASH", script: []byte{btcscript.OP_PUBKEYHASH}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_PUBKEYHASH", }, { name: "invalid opcode OP_INVALIDOPCODE", script: []byte{btcscript.OP_INVALIDOPCODE}, - expectedReturn: btcscript.StackErrInvalidOpcode, + expectedReturn: btcscript.ErrStackInvalidOpcode, disassembly: "OP_INVALIDOPCODE", }, } @@ -4321,7 +4321,7 @@ func testOpcode(t *testing.T, test *detailedTest) { test.name, err) } _, err = engine.DisasmScript(2) - if err != btcscript.StackErrInvalidIndex { + if err != btcscript.ErrStackInvalidIndex { t.Errorf("%s: got unexpected error for invalid "+ "disassembly index: \"%v\"", test.name, err) } diff --git a/script.go b/script.go index f2939fa2..148e8c7b 100644 --- a/script.go +++ b/script.go @@ -21,110 +21,110 @@ import ( ) var ( - // StackErrShortScript is returned if the script has an opcode that is + // ErrStackShortScript is returned if the script has an opcode that is // too long for the length of the script. - StackErrShortScript = errors.New("execute past end of script") + ErrStackShortScript = errors.New("execute past end of script") - // StackErrLongScript is returned if the script has an opcode that is + // ErrStackLongScript is returned if the script has an opcode that is // too long for the length of the script. - StackErrLongScript = errors.New("script is longer than maximum allowed") + ErrStackLongScript = errors.New("script is longer than maximum allowed") - // StackErrUnderflow is returned if an opcode requires more items on the - // stack than is present. - StackErrUnderflow = errors.New("stack underflow") + // ErrStackUnderflow is returned if an opcode requires more items on the + // stack than is present.f + ErrStackUnderflow = errors.New("stack underflow") - // StackErrInvalidArgs is returned if the argument for an opcode is out + // ErrStackInvalidArgs is returned if the argument for an opcode is out // of acceptable range. - StackErrInvalidArgs = errors.New("invalid argument") + ErrStackInvalidArgs = errors.New("invalid argument") - // StackErrOpDisabled is returned when a disabled opcode is encountered + // ErrStackOpDisabled is returned when a disabled opcode is encountered // in the script. - StackErrOpDisabled = errors.New("Disabled Opcode") + ErrStackOpDisabled = errors.New("Disabled Opcode") - // StackErrVerifyFailed is returned when one of the OP_VERIFY or + // ErrStackVerifyFailed is returned when one of the OP_VERIFY or // OP_*VERIFY instructions is executed and the conditions fails. - StackErrVerifyFailed = errors.New("Verify failed") + ErrStackVerifyFailed = errors.New("Verify failed") - // StackErrNumberTooBig is returned when the argument for an opcode that + // ErrStackNumberTooBig is returned when the argument for an opcode that // should be an offset is obviously far too large. - StackErrNumberTooBig = errors.New("number too big") + ErrStackNumberTooBig = errors.New("number too big") - // StackErrInvalidOpcode is returned when an opcode marked as invalid or + // ErrStackInvalidOpcode is returned when an opcode marked as invalid or // a completely undefined opcode is encountered. - StackErrInvalidOpcode = errors.New("Invalid Opcode") + ErrStackInvalidOpcode = errors.New("Invalid Opcode") - // StackErrReservedOpcode is returned when an opcode marked as reserved + // ErrStackReservedOpcode is returned when an opcode marked as reserved // is encountered. - StackErrReservedOpcode = errors.New("Reserved Opcode") + ErrStackReservedOpcode = errors.New("Reserved Opcode") - // StackErrEarlyReturn is returned when OP_RETURN is executed in the + // ErrStackEarlyReturn is returned when OP_RETURN is executed in the // script. - StackErrEarlyReturn = errors.New("Script returned early") + ErrStackEarlyReturn = errors.New("Script returned early") - // StackErrNoIf is returned if an OP_ELSE or OP_ENDIF is encountered + // ErrStackNoIf is returned if an OP_ELSE or OP_ENDIF is encountered // without first having an OP_IF or OP_NOTIF in the script. - StackErrNoIf = errors.New("OP_ELSE or OP_ENDIF with no matching OP_IF") + ErrStackNoIf = errors.New("OP_ELSE or OP_ENDIF with no matching OP_IF") - // StackErrMissingEndif is returned if the end of a script is reached + // ErrStackMissingEndif is returned if the end of a script is reached // without and OP_ENDIF to correspond to a conditional expression. - StackErrMissingEndif = fmt.Errorf("execute fail, in conditional execution") + ErrStackMissingEndif = fmt.Errorf("execute fail, in conditional execution") - // StackErrTooManyPubkeys is returned if an OP_CHECKMULTISIG is + // ErrStackTooManyPubkeys is returned if an OP_CHECKMULTISIG is // encountered with more than MaxPubKeysPerMultiSig pubkeys present. - StackErrTooManyPubkeys = errors.New("Invalid pubkey count in OP_CHECKMULTISIG") + ErrStackTooManyPubkeys = errors.New("Invalid pubkey count in OP_CHECKMULTISIG") - // StackErrTooManyOperations is returned if a script has more than + // ErrStackTooManyOperations is returned if a script has more than // MaxOpsPerScript opcodes that do not push data. - StackErrTooManyOperations = errors.New("Too many operations in script") + ErrStackTooManyOperations = errors.New("Too many operations in script") - // StackErrElementTooBig is returned if the size of an element to be + // ErrStackElementTooBig is returned if the size of an element to be // pushed to the stack is over MaxScriptElementSize. - StackErrElementTooBig = errors.New("Element in script too large") + ErrStackElementTooBig = errors.New("Element in script too large") - // StackErrUnknownAddress is returned when ScriptToAddrHash does not + // ErrStackUnknownAddress is returned when ScriptToAddrHash does not // recognise the pattern of the script and thus can not find the address // for payment. - StackErrUnknownAddress = errors.New("non-recognised address") + ErrStackUnknownAddress = errors.New("non-recognised address") - // StackErrScriptFailed is returned when at the end of a script the + // ErrStackScriptFailed is returned when at the end of a script the // boolean on top of the stack is false signifying that the script has // failed. - StackErrScriptFailed = errors.New("execute fail, fail on stack") + ErrStackScriptFailed = errors.New("execute fail, fail on stack") - // StackErrScriptUnfinished is returned when CheckErrorCondition is + // ErrStackScriptUnfinished is returned when CheckErrorCondition is // called on a script that has not finished executing. - StackErrScriptUnfinished = errors.New("Error check when script unfinished") + ErrStackScriptUnfinished = errors.New("Error check when script unfinished") - // StackErrEmpyStack is returned when the stack is empty at the end of + // ErrStackEmptyStack is returned when the stack is empty at the end of // execution. Normal operation requires that a boolean is on top of the // stack when the scripts have finished executing. - StackErrEmptyStack = errors.New("Stack empty at end of execution") + ErrStackEmptyStack = errors.New("Stack empty at end of execution") - // StackErrP2SHNonPushOnly is returned when a Pay-to-Script-Hash + // ErrStackP2SHNonPushOnly is returned when a Pay-to-Script-Hash // transaction is encountered and the ScriptSig does operations other // than push data (in violation of bip16). - StackErrP2SHNonPushOnly = errors.New("pay to script hash with non " + + ErrStackP2SHNonPushOnly = errors.New("pay to script hash with non " + "pushonly input") - // StackErrInvalidParseType is an internal error returned from + // ErrStackInvalidParseType is an internal error returned from // ScriptToAddrHash ony if the internal data tables are wrong. - StackErrInvalidParseType = errors.New("internal error: invalid parsetype found") + ErrStackInvalidParseType = errors.New("internal error: invalid parsetype found") - // StackErrInvalidAddrOffset is an internal error returned from + // ErrStackInvalidAddrOffset is an internal error returned from // ScriptToAddrHash ony if the internal data tables are wrong. - StackErrInvalidAddrOffset = errors.New("internal error: invalid offset found") + ErrStackInvalidAddrOffset = errors.New("internal error: invalid offset found") - // StackErrInvalidIndex is returned when an out-of-bounds index was + // ErrStackInvalidIndex is returned when an out-of-bounds index was // passed to a function. - StackErrInvalidIndex = errors.New("Invalid script index") + ErrStackInvalidIndex = errors.New("Invalid script index") - // StackErrNonPushOnly is returned when ScriptInfo is called with a + // ErrStackNonPushOnly is returned when ScriptInfo is called with a // pkScript that peforms operations other that pushing data to the stack. - StackErrNonPushOnly = errors.New("SigScript is non pushonly") + ErrStackNonPushOnly = errors.New("SigScript is non pushonly") - // StackErrOverflow is returned when stack and altstack combined depth + // ErrStackOverflow is returned when stack and altstack combined depth // is over the limit. - StackErrOverflow = errors.New("Stacks overflowed") + ErrStackOverflow = errors.New("Stacks overflowed") ) const ( @@ -421,7 +421,7 @@ func parseScriptTemplate(script []byte, opcodemap map[byte]*opcode) ([]parsedOpc instr := script[i] op, ok := opcodemap[instr] if !ok { - return retScript, StackErrInvalidOpcode + return retScript, ErrStackInvalidOpcode } pop := parsedOpcode{opcode: op} // parse data out of instruction. @@ -431,7 +431,7 @@ func parseScriptTemplate(script []byte, opcodemap map[byte]*opcode) ([]parsedOpc i++ case op.length > 1: if len(script[i:]) < op.length { - return retScript, StackErrShortScript + return retScript, ErrStackShortScript } // slice out the data. pop.data = script[i+1 : i+op.length] @@ -441,7 +441,7 @@ func parseScriptTemplate(script []byte, opcodemap map[byte]*opcode) ([]parsedOpc off := i + 1 if len(script[off:]) < -op.length { - return retScript, StackErrShortScript + return retScript, ErrStackShortScript } // Next -length bytes are little endian length of data. @@ -466,7 +466,7 @@ func parseScriptTemplate(script []byte, opcodemap map[byte]*opcode) ([]parsedOpc // Disallow entries that do not fit script or were // sign extended. if int(l) > len(script[off:]) || int(l) < 0 { - return retScript, StackErrShortScript + return retScript, ErrStackShortScript } pop.data = script[off : off+int(l)] i += 1 - op.length + int(l) @@ -528,7 +528,7 @@ func NewScript(scriptSig []byte, scriptPubKey []byte, txidx int, tx *btcwire.Msg m.scripts = make([][]parsedOpcode, len(scripts)) for i, scr := range scripts { if len(scr) > maxScriptSize { - return nil, StackErrLongScript + return nil, ErrStackLongScript } var err error m.scripts[i], err = parseScript(scr) @@ -551,7 +551,7 @@ func NewScript(scriptSig []byte, scriptPubKey []byte, txidx int, tx *btcwire.Msg // if we are pay to scripthash then we only accept input // scripts that push data if !isPushOnly(m.scripts[0]) { - return nil, StackErrP2SHNonPushOnly + return nil, ErrStackP2SHNonPushOnly } m.bip16 = true } @@ -611,10 +611,10 @@ func (s *Script) CheckErrorCondition() (err error) { // Check we are actually done. if pc is past the end of script array // then we have run out of scripts to run. if s.scriptidx < len(s.scripts) { - return StackErrScriptUnfinished + return ErrStackScriptUnfinished } if s.dstack.Depth() < 1 { - return StackErrEmptyStack + return ErrStackEmptyStack } v, err := s.dstack.PopBool() if err == nil && v == false { @@ -625,7 +625,7 @@ func (s *Script) CheckErrorCondition() (err error) { return fmt.Sprintf("scripts failed: script0: %s\n"+ "script1: %s", dis0, dis1) })) - err = StackErrScriptFailed + err = ErrStackScriptFailed } return err } @@ -649,7 +649,7 @@ func (m *Script) Step() (done bool, err error) { } if m.dstack.Depth()+m.astack.Depth() > maxStackSize { - return false, StackErrOverflow + return false, ErrStackOverflow } // prepare for next instruction @@ -657,7 +657,7 @@ func (m *Script) Step() (done bool, err error) { if m.scriptoff >= len(m.scripts[m.scriptidx]) { // Illegal to have an `if' that straddles two scripts. if err == nil && len(m.condStack) != 1 { - return false, StackErrMissingEndif + return false, ErrStackMissingEndif } // alt stack doesn't persist. @@ -728,7 +728,7 @@ func (m *Script) validPC() error { // ``idx''. Where 0 is the scriptSig and 1 is the scriptPubKey. func (m *Script) DisasmScript(idx int) (disstr string, err error) { if idx >= len(m.scripts) { - return "", StackErrInvalidIndex + return "", ErrStackInvalidIndex } for i := range m.scripts[idx] { disstr = disstr + m.disasm(idx, i) + "\n" @@ -1561,7 +1561,7 @@ func CalcScriptInfo(sigscript, pkscript []byte, bip16 bool) (*ScriptInfo, error) // Can't have a pkScript that doesn't just push data. if !isPushOnly(sigPops) { - return nil, StackErrNonPushOnly + return nil, ErrStackNonPushOnly } si.ExpectedInputs = expectedInputs(pkPops, si.PkScriptClass) @@ -1622,7 +1622,7 @@ func CalcMultiSigStats(script []byte) (int, int, error) { // items must be on the stack per: // OP_1 PUBKEY OP_1 OP_CHECKMULTISIG if len(pops) < 4 { - return 0, 0, StackErrUnderflow + return 0, 0, ErrStackUnderflow } numSigs := asSmallInt(pops[0].opcode) diff --git a/script_test.go b/script_test.go index 23ef4032..b859fae6 100644 --- a/script_test.go +++ b/script_test.go @@ -326,7 +326,7 @@ var txTests = []txTest{ 0x12, 0xa3, btcscript.OP_CHECKSIG, }, idx: 0, - err: btcscript.StackErrScriptFailed, + err: btcscript.ErrStackScriptFailed, nSigOps: 1, scriptInfo: btcscript.ScriptInfo{ PkScriptClass: btcscript.PubKeyTy, @@ -1082,7 +1082,7 @@ var txTests = []txTest{ idx: 1, bip16: false, nSigOps: 0, // multisig is in the pkScript! - scriptInfoErr: btcscript.StackErrNonPushOnly, + scriptInfoErr: btcscript.ErrStackNonPushOnly, }, // same as previous but with one byte changed to make signature fail { @@ -1204,9 +1204,9 @@ var txTests = []txTest{ }, idx: 1, bip16: false, - err: btcscript.StackErrScriptFailed, + err: btcscript.ErrStackScriptFailed, nSigOps: 0, // multisig is in the pkScript! - scriptInfoErr: btcscript.StackErrNonPushOnly, + scriptInfoErr: btcscript.ErrStackNonPushOnly, }, // taken from tx b2d93dfd0b2c1a380e55e76a8d9cb3075dec9f4474e9485be008c337fd62c1f7 // on testnet @@ -1391,7 +1391,7 @@ var txTests = []txTest{ btcscript.OP_EQUAL, }, idx: 0, - err: btcscript.StackErrScriptFailed, + err: btcscript.ErrStackScriptFailed, bip16: true, nSigOps: 0, // no signature ops in the pushed script. scriptInfo: btcscript.ScriptInfo{ @@ -1456,9 +1456,9 @@ var txTests = []txTest{ btcscript.OP_EQUAL, }, idx: 0, - err: btcscript.StackErrShortScript, + err: btcscript.ErrStackShortScript, bip16: true, - scriptInfoErr: btcscript.StackErrShortScript, + scriptInfoErr: btcscript.ErrStackShortScript, }, { // sigscript changed so to be non pushonly. @@ -1519,10 +1519,10 @@ var txTests = []txTest{ btcscript.OP_EQUAL, }, idx: 0, - parseErr: btcscript.StackErrP2SHNonPushOnly, + parseErr: btcscript.ErrStackP2SHNonPushOnly, bip16: true, nSigOps: 0, // no signature ops in the pushed script. - scriptInfoErr: btcscript.StackErrNonPushOnly, + scriptInfoErr: btcscript.ErrStackNonPushOnly, }, { // sigscript changed so to be non pushonly. @@ -1663,7 +1663,7 @@ func TestGetPreciseSignOps(t *testing.T) { { name: "scriptSig doesn't parse", scriptSig: []byte{btcscript.OP_PUSHDATA1, 2}, - err: btcscript.StackErrShortScript, + err: btcscript.ErrStackShortScript, }, { name: "scriptSig isn't push only", @@ -1686,7 +1686,7 @@ func TestGetPreciseSignOps(t *testing.T) { name: "pushed script doesn't parse", scriptSig: []byte{btcscript.OP_DATA_2, btcscript.OP_PUSHDATA1, 2}, - err: btcscript.StackErrShortScript, + err: btcscript.ErrStackShortScript, }, } // The signature in the p2sh script is nonsensical for the tests since @@ -1766,7 +1766,7 @@ func TestScriptInfo(t *testing.T) { 0xc4, 0xf5, 0x9c, }, bip16: true, - scriptInfoErr: btcscript.StackErrShortScript, + scriptInfoErr: btcscript.ErrStackShortScript, }, { name: "sigScript doesn't parse", @@ -1786,7 +1786,7 @@ func TestScriptInfo(t *testing.T) { 0xc4, 0xf5, 0x9c, 0x74, btcscript.OP_EQUAL, }, bip16: true, - scriptInfoErr: btcscript.StackErrShortScript, + scriptInfoErr: btcscript.ErrStackShortScript, }, { // Invented scripts, the hashes do not match @@ -1945,13 +1945,13 @@ var removeOpcodeTests = []removeOpcodeTest{ name: "invalid length (insruction)", before: []byte{btcscript.OP_PUSHDATA1}, remove: btcscript.OP_CODESEPARATOR, - err: btcscript.StackErrShortScript, + err: btcscript.ErrStackShortScript, }, { name: "invalid length (data)", before: []byte{btcscript.OP_PUSHDATA1, 255, 254}, remove: btcscript.OP_CODESEPARATOR, - err: btcscript.StackErrShortScript, + err: btcscript.ErrStackShortScript, }, } @@ -2083,13 +2083,13 @@ var removeOpcodeByDataTests = []removeOpcodeByDataTest{ name: "invalid length (instruction)", before: []byte{btcscript.OP_PUSHDATA1}, remove: []byte{1, 2, 3, 4}, - err: btcscript.StackErrShortScript, + err: btcscript.ErrStackShortScript, }, { name: "invalid length (data)", before: []byte{btcscript.OP_PUSHDATA1, 255, 254}, remove: []byte{1, 2, 3, 4}, - err: btcscript.StackErrShortScript, + err: btcscript.ErrStackShortScript, }, } @@ -2493,7 +2493,7 @@ func TestCheckErrorCondition(t *testing.T) { } err = engine.CheckErrorCondition() - if err != btcscript.StackErrScriptUnfinished { + if err != btcscript.ErrStackScriptUnfinished { t.Errorf("got unexepected error %v on %dth iteration", err, i) return @@ -4638,7 +4638,7 @@ func TestCalcMultiSigStats(t *testing.T) { 0x71, 0x05, 0xcd, 0x6a, 0x82, 0x8e, 0x03, 0x90, 0x9a, 0x67, 0x96, 0x2e, 0x0e, 0xa1, 0xf6, 0x1d, }, - expected: btcscript.StackErrShortScript, + expected: btcscript.ErrStackShortScript, }, { name: "stack underflow", @@ -4653,7 +4653,7 @@ func TestCalcMultiSigStats(t *testing.T) { 0xeb, 0x64, 0x9f, 0x6b, 0xc3, 0xf4, 0xce, 0xf3, 0x08, }, - expected: btcscript.StackErrUnderflow, + expected: btcscript.ErrStackUnderflow, }, { name: "multisig script", diff --git a/stack.go b/stack.go index ab82ac6a..19aadf9f 100644 --- a/stack.go +++ b/stack.go @@ -14,7 +14,7 @@ import ( func asInt(v []byte) (*big.Int, error) { // Only 32bit numbers allowed. if len(v) > 4 { - return nil, StackErrNumberTooBig + return nil, ErrStackNumberTooBig } if len(v) == 0 { return big.NewInt(0), nil @@ -149,7 +149,7 @@ func (s *Stack) PopBool() (bool, error) { func (s *Stack) PeekByteArray(idx int) (so []byte, err error) { sz := len(s.stk) if idx < 0 || idx >= sz { - return nil, StackErrUnderflow + return nil, ErrStackUnderflow } return s.stk[sz-idx-1], nil } @@ -177,7 +177,7 @@ func (s *Stack) PeekBool(idx int) (i bool, err error) { func (s *Stack) nipN(idx int) (so []byte, err error) { sz := len(s.stk) if idx < 0 || idx > sz-1 { - err = StackErrUnderflow + err = ErrStackUnderflow return } so = s.stk[sz-idx-1] @@ -231,7 +231,7 @@ func (s *Stack) Depth() (sz int) { // DropN(2): 1,2,3 -> 1 func (s *Stack) DropN(n int) error { if n < 1 { - return StackErrInvalidArgs + return ErrStackInvalidArgs } for ; n > 0; n-- { _, err := s.PopByteArray() @@ -248,7 +248,7 @@ func (s *Stack) DropN(n int) error { // DupN(2): 1,2,3 -> 1,2,3,2,3 func (s *Stack) DupN(n int) error { if n < 1 { - return StackErrInvalidArgs + return ErrStackInvalidArgs } // Iteratively duplicate the value n-1 down the stack n times. // this leaves us with an in-order duplicate of the top N items on the @@ -268,7 +268,7 @@ func (s *Stack) DupN(n int) error { // RotN(1): 1,2,3 -> 2,3,1 func (s *Stack) RotN(n int) error { if n < 1 { - return StackErrInvalidArgs + return ErrStackInvalidArgs } entry := 3*n - 1 // Nip the 3n-1th item from the stack to the top n times to rotate @@ -290,7 +290,7 @@ func (s *Stack) RotN(n int) error { // SwapN(2): 1,2,3,4 -> 3,4,1,2 func (s *Stack) SwapN(n int) error { if n < 1 { - return StackErrInvalidArgs + return ErrStackInvalidArgs } entry := 2*n - 1 for i := n; i > 0; i-- { @@ -311,7 +311,7 @@ func (s *Stack) SwapN(n int) error { // OverN(2): 1,2,3,4 -> 1,2,3,4,1,2 func (s *Stack) OverN(n int) error { if n < 1 { - return StackErrInvalidArgs + return ErrStackInvalidArgs } // Copy 2n-1th entry to top of the stack entry := 2*n - 1 diff --git a/stack_test.go b/stack_test.go index 0c1781fb..2448ebf6 100644 --- a/stack_test.go +++ b/stack_test.go @@ -39,7 +39,7 @@ var stackTests = []stackTest{ _, err := stack.PeekByteArray(5) return err }, - btcscript.StackErrUnderflow, + btcscript.ErrStackUnderflow, [][]byte{}, }, { @@ -49,7 +49,7 @@ var stackTests = []stackTest{ _, err := stack.PeekInt(5) return err }, - btcscript.StackErrUnderflow, + btcscript.ErrStackUnderflow, [][]byte{}, }, { @@ -59,7 +59,7 @@ var stackTests = []stackTest{ _, err := stack.PeekBool(5) return err }, - btcscript.StackErrUnderflow, + btcscript.ErrStackUnderflow, [][]byte{}, }, { @@ -121,7 +121,7 @@ var stackTests = []stackTest{ } return nil }, - btcscript.StackErrUnderflow, + btcscript.ErrStackUnderflow, [][]byte{}, }, { @@ -169,7 +169,7 @@ var stackTests = []stackTest{ return nil }, - btcscript.StackErrUnderflow, + btcscript.ErrStackUnderflow, [][]byte{}, }, { @@ -411,7 +411,7 @@ var stackTests = []stackTest{ return nil }, - btcscript.StackErrInvalidArgs, + btcscript.ErrStackInvalidArgs, [][]byte{}, }, { @@ -425,7 +425,7 @@ var stackTests = []stackTest{ return nil }, - btcscript.StackErrInvalidArgs, + btcscript.ErrStackInvalidArgs, [][]byte{}, }, { @@ -439,7 +439,7 @@ var stackTests = []stackTest{ return nil }, - btcscript.StackErrUnderflow, + btcscript.ErrStackUnderflow, [][]byte{}, }, { @@ -453,7 +453,7 @@ var stackTests = []stackTest{ return nil }, - btcscript.StackErrInvalidArgs, + btcscript.ErrStackInvalidArgs, [][]byte{}, }, { @@ -602,7 +602,7 @@ var stackTests = []stackTest{ // bite off more than we can chew return stack.NipN(3) }, - btcscript.StackErrUnderflow, + btcscript.ErrStackUnderflow, [][]byte{{2}, {3}}, }, { @@ -612,7 +612,7 @@ var stackTests = []stackTest{ // bite off more than we can chew return stack.NipN(3) }, - btcscript.StackErrUnderflow, + btcscript.ErrStackUnderflow, [][]byte{{2}, {3}}, }, { @@ -630,7 +630,7 @@ var stackTests = []stackTest{ func(stack *btcscript.Stack) error { return stack.Tuck() }, - btcscript.StackErrUnderflow, + btcscript.ErrStackUnderflow, [][]byte{}, }, { @@ -639,7 +639,7 @@ var stackTests = []stackTest{ func(stack *btcscript.Stack) error { return stack.Tuck() }, - btcscript.StackErrUnderflow, + btcscript.ErrStackUnderflow, [][]byte{}, }, { @@ -684,7 +684,7 @@ var stackTests = []stackTest{ func(stack *btcscript.Stack) error { return stack.DropN(5) }, - btcscript.StackErrUnderflow, + btcscript.ErrStackUnderflow, [][]byte{}, }, { @@ -693,7 +693,7 @@ var stackTests = []stackTest{ func(stack *btcscript.Stack) error { return stack.DropN(0) }, - btcscript.StackErrInvalidArgs, + btcscript.ErrStackInvalidArgs, [][]byte{}, }, { @@ -720,7 +720,7 @@ var stackTests = []stackTest{ func(stack *btcscript.Stack) error { return stack.RotN(1) }, - btcscript.StackErrUnderflow, + btcscript.ErrStackUnderflow, [][]byte{}, }, { @@ -729,7 +729,7 @@ var stackTests = []stackTest{ func(stack *btcscript.Stack) error { return stack.RotN(0) }, - btcscript.StackErrInvalidArgs, + btcscript.ErrStackInvalidArgs, [][]byte{}, }, { @@ -756,7 +756,7 @@ var stackTests = []stackTest{ func(stack *btcscript.Stack) error { return stack.SwapN(1) }, - btcscript.StackErrUnderflow, + btcscript.ErrStackUnderflow, [][]byte{}, }, { @@ -765,7 +765,7 @@ var stackTests = []stackTest{ func(stack *btcscript.Stack) error { return stack.SwapN(0) }, - btcscript.StackErrInvalidArgs, + btcscript.ErrStackInvalidArgs, [][]byte{}, }, { @@ -792,7 +792,7 @@ var stackTests = []stackTest{ func(stack *btcscript.Stack) error { return stack.OverN(1) }, - btcscript.StackErrUnderflow, + btcscript.ErrStackUnderflow, [][]byte{}, }, { @@ -801,7 +801,7 @@ var stackTests = []stackTest{ func(stack *btcscript.Stack) error { return stack.OverN(0) }, - btcscript.StackErrInvalidArgs, + btcscript.ErrStackInvalidArgs, [][]byte{}, }, { @@ -828,7 +828,7 @@ var stackTests = []stackTest{ func(stack *btcscript.Stack) error { return stack.PickN(1) }, - btcscript.StackErrUnderflow, + btcscript.ErrStackUnderflow, [][]byte{}, }, { @@ -855,7 +855,7 @@ var stackTests = []stackTest{ func(stack *btcscript.Stack) error { return stack.RollN(1) }, - btcscript.StackErrUnderflow, + btcscript.ErrStackUnderflow, [][]byte{}, }, { @@ -958,7 +958,7 @@ var stackTests = []stackTest{ _, err := stack.PopInt() return err }, - btcscript.StackErrUnderflow, + btcscript.ErrStackUnderflow, [][]byte{}, }, } From ce0a3343294098214c044e1eb6d91379cfabc97f Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Sun, 12 Oct 2014 19:39:01 -0500 Subject: [PATCH 153/174] Comment ScriptInfo struct according to standards. Found by golint. --- script.go | 95 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 50 insertions(+), 45 deletions(-) diff --git a/script.go b/script.go index 148e8c7b..255be56b 100644 --- a/script.go +++ b/script.go @@ -635,67 +635,67 @@ func (s *Script) CheckErrorCondition() (err error) { // will return true in the case that the last opcode was successfully executed. // if an error is returned then the result of calling Step or any other method // is undefined. -func (m *Script) Step() (done bool, err error) { +func (s *Script) Step() (done bool, err error) { // verify that it is pointing to a valid script address - err = m.validPC() + err = s.validPC() if err != nil { return true, err } - opcode := m.scripts[m.scriptidx][m.scriptoff] + opcode := s.scripts[s.scriptidx][s.scriptoff] - err = opcode.exec(m) + err = opcode.exec(s) if err != nil { return true, err } - if m.dstack.Depth()+m.astack.Depth() > maxStackSize { + if s.dstack.Depth()+s.astack.Depth() > maxStackSize { return false, ErrStackOverflow } // prepare for next instruction - m.scriptoff++ - if m.scriptoff >= len(m.scripts[m.scriptidx]) { + s.scriptoff++ + if s.scriptoff >= len(s.scripts[s.scriptidx]) { // Illegal to have an `if' that straddles two scripts. - if err == nil && len(m.condStack) != 1 { + if err == nil && len(s.condStack) != 1 { return false, ErrStackMissingEndif } // alt stack doesn't persist. - _ = m.astack.DropN(m.astack.Depth()) + _ = s.astack.DropN(s.astack.Depth()) - m.numOps = 0 // number of ops is per script. - m.scriptoff = 0 - if m.scriptidx == 0 && m.bip16 { - m.scriptidx++ - m.savedFirstStack = m.GetStack() - } else if m.scriptidx == 1 && m.bip16 { + s.numOps = 0 // number of ops is per script. + s.scriptoff = 0 + if s.scriptidx == 0 && s.bip16 { + s.scriptidx++ + s.savedFirstStack = s.GetStack() + } else if s.scriptidx == 1 && s.bip16 { // Put us past the end for CheckErrorCondition() - m.scriptidx++ + s.scriptidx++ // We check script ran ok, if so then we pull // the script out of the first stack and executre that. - err := m.CheckErrorCondition() + err := s.CheckErrorCondition() if err != nil { return false, err } - script := m.savedFirstStack[len(m.savedFirstStack)-1] + script := s.savedFirstStack[len(s.savedFirstStack)-1] pops, err := parseScript(script) if err != nil { return false, err } - m.scripts = append(m.scripts, pops) + s.scripts = append(s.scripts, pops) // Set stack to be the stack from first script // minus the script itself - m.SetStack(m.savedFirstStack[:len(m.savedFirstStack)-1]) + s.SetStack(s.savedFirstStack[:len(s.savedFirstStack)-1]) } else { - m.scriptidx++ + s.scriptidx++ } // there are zero length scripts in the wild - if m.scriptidx < len(m.scripts) && m.scriptoff >= len(m.scripts[m.scriptidx]) { - m.scriptidx++ + if s.scriptidx < len(s.scripts) && s.scriptoff >= len(s.scripts[s.scriptidx]) { + s.scriptidx++ } - m.lastcodesep = 0 - if m.scriptidx >= len(m.scripts) { + s.lastcodesep = 0 + if s.scriptidx >= len(s.scripts) { return true, nil } } @@ -704,55 +704,55 @@ func (m *Script) Step() (done bool, err error) { // curPC returns either the current script and offset, or an error if the // position isn't valid. -func (m *Script) curPC() (script int, off int, err error) { - err = m.validPC() +func (s *Script) curPC() (script int, off int, err error) { + err = s.validPC() if err != nil { return 0, 0, err } - return m.scriptidx, m.scriptoff, nil + return s.scriptidx, s.scriptoff, nil } // validPC returns an error if the current script position is valid for // execution, nil otherwise. -func (m *Script) validPC() error { - if m.scriptidx >= len(m.scripts) { - return fmt.Errorf("Past input scripts %v:%v %v:xxxx", m.scriptidx, m.scriptoff, len(m.scripts)) +func (s *Script) validPC() error { + if s.scriptidx >= len(s.scripts) { + return fmt.Errorf("Past input scripts %v:%v %v:xxxx", s.scriptidx, s.scriptoff, len(s.scripts)) } - if m.scriptoff >= len(m.scripts[m.scriptidx]) { - return fmt.Errorf("Past input scripts %v:%v %v:%04d", m.scriptidx, m.scriptoff, m.scriptidx, len(m.scripts[m.scriptidx])) + if s.scriptoff >= len(s.scripts[s.scriptidx]) { + return fmt.Errorf("Past input scripts %v:%v %v:%04d", s.scriptidx, s.scriptoff, s.scriptidx, len(s.scripts[s.scriptidx])) } return nil } // DisasmScript returns the disassembly string for the script at offset // ``idx''. Where 0 is the scriptSig and 1 is the scriptPubKey. -func (m *Script) DisasmScript(idx int) (disstr string, err error) { - if idx >= len(m.scripts) { +func (s *Script) DisasmScript(idx int) (disstr string, err error) { + if idx >= len(s.scripts) { return "", ErrStackInvalidIndex } - for i := range m.scripts[idx] { - disstr = disstr + m.disasm(idx, i) + "\n" + for i := range s.scripts[idx] { + disstr = disstr + s.disasm(idx, i) + "\n" } return disstr, nil } // DisasmPC returns the string for the disassembly of the opcode that will be // next to execute when Step() is called. -func (m *Script) DisasmPC() (disstr string, err error) { - scriptidx, scriptoff, err := m.curPC() +func (s *Script) DisasmPC() (disstr string, err error) { + scriptidx, scriptoff, err := s.curPC() if err != nil { return "", err } - return m.disasm(scriptidx, scriptoff), nil + return s.disasm(scriptidx, scriptoff), nil } // disasm is a helper member to produce the output for DisasmPC and // DisasmScript. It produces the opcode prefixed by the program counter at the // provided position in the script. it does no error checking and leaves that // to the caller to provide a valid offse. -func (m *Script) disasm(scriptidx int, scriptoff int) string { +func (s *Script) disasm(scriptidx int, scriptoff int) string { return fmt.Sprintf("%02x:%04x: %s", scriptidx, scriptoff, - m.scripts[scriptidx][scriptoff].print(false)) + s.scripts[scriptidx][scriptoff].print(false)) } // subScript will return the script since the last OP_CODESEPARATOR @@ -1526,16 +1526,21 @@ func expectedInputs(pops []parsedOpcode, class ScriptClass) int { } } +// ScriptInfo houses information about a script pair that is determined by +// CalcScriptInfo. type ScriptInfo struct { // The class of the sigscript, equivalent to calling GetScriptClass // on the sigScript. PkScriptClass ScriptClass - // the number of inputs provided by the pkScript + + // NumInputs is the number of inputs provided by the pkScript. NumInputs int - // the number of outputs required by sigScript and any + + // ExpectedInputs is the number of outputs required by sigScript and any // pay-to-script-hash scripts. The number will be -1 if unknown. ExpectedInputs int - // The nubmer of signature operations in the scriptpair. + + // SigOps is the nubmer of signature operations in the script pair. SigOps int } From d5cc72dc278d87ec4c348af7f80cba17aa992ffc Mon Sep 17 00:00:00 2001 From: Jimmy Song Date: Mon, 29 Sep 2014 16:31:26 -0500 Subject: [PATCH 154/174] use btcec structs instead of ecdsa structs --- opcode.go | 6 ++-- script.go | 26 +++++++-------- script_test.go | 87 +++++++++++++++----------------------------------- 3 files changed, 39 insertions(+), 80 deletions(-) diff --git a/opcode.go b/opcode.go index aa983b0a..99071802 100644 --- a/opcode.go +++ b/opcode.go @@ -6,7 +6,6 @@ package btcscript import ( "bytes" - "crypto/ecdsa" "crypto/sha1" "encoding/binary" "encoding/hex" @@ -1812,7 +1811,7 @@ func opcodeCheckSig(op *parsedOpcode, s *Script) error { hex.Dump(pkStr), pubKey.X, pubKey.Y, signature.R, signature.S, hex.Dump(hash)) })) - ok := ecdsa.Verify(pubKey.ToECDSA(), hash, signature.R, signature.S) + ok := signature.Verify(hash, pubKey) s.dstack.PushBool(ok) return nil } @@ -1947,8 +1946,7 @@ func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error { continue } } - success = ecdsa.Verify(pubKeys[curPk].ToECDSA(), hash, - signatures[i].s.R, signatures[i].s.S) + success = signatures[i].s.Verify(hash, pubKeys[curPk]) if success { break inner } diff --git a/script.go b/script.go index 255be56b..a1e86c07 100644 --- a/script.go +++ b/script.go @@ -6,7 +6,6 @@ package btcscript import ( "bytes" - "crypto/ecdsa" "crypto/rand" "encoding/binary" "errors" @@ -1100,7 +1099,7 @@ func MultiSigScript(pubkeys []*btcutil.AddressPubKey, nrequired int) ([]byte, er // serialized in either a compressed or uncompressed format based on // compress. This format must match the same format used to generate // the payment address, or the script validation will fail. -func SignatureScript(tx *btcwire.MsgTx, idx int, subscript []byte, hashType SigHashType, privKey *ecdsa.PrivateKey, compress bool) ([]byte, error) { +func SignatureScript(tx *btcwire.MsgTx, idx int, subscript []byte, hashType SigHashType, privKey *btcec.PrivateKey, compress bool) ([]byte, error) { sig, err := signTxOutput(tx, idx, subscript, hashType, privKey) if err != nil { return nil, err @@ -1118,29 +1117,28 @@ func SignatureScript(tx *btcwire.MsgTx, idx int, subscript []byte, hashType SigH } func signTxOutput(tx *btcwire.MsgTx, idx int, subScript []byte, hashType SigHashType, - key *ecdsa.PrivateKey) ([]byte, error) { + key *btcec.PrivateKey) ([]byte, error) { return signTxOutputCustomReader(rand.Reader, tx, idx, subScript, hashType, key) } func signTxOutputCustomReader(reader io.Reader, tx *btcwire.MsgTx, idx int, - subScript []byte, hashType SigHashType, key *ecdsa.PrivateKey) ([]byte, error) { + subScript []byte, hashType SigHashType, key *btcec.PrivateKey) ([]byte, error) { parsedScript, err := parseScript(subScript) if err != nil { return nil, fmt.Errorf("cannot parse output script: %v", err) } hash := calcScriptHash(parsedScript, hashType, tx, idx) - r, s, err := ecdsa.Sign(reader, key, hash) + signature, err := key.Sign(hash) if err != nil { return nil, fmt.Errorf("cannot sign tx input: %s", err) } - return append((&btcec.Signature{R: r, S: s}).Serialize(), - byte(hashType)), nil + return append(signature.Serialize(), byte(hashType)), nil } -func p2pkSignatureScript(tx *btcwire.MsgTx, idx int, subScript []byte, hashType SigHashType, privKey *ecdsa.PrivateKey) ([]byte, error) { +func p2pkSignatureScript(tx *btcwire.MsgTx, idx int, subScript []byte, hashType SigHashType, privKey *btcec.PrivateKey) ([]byte, error) { sig, err := signTxOutput(tx, idx, subScript, hashType, privKey) if err != nil { return nil, err @@ -1384,9 +1382,7 @@ sigLoop: // If it matches we put it in the map. We only // can take one signature per public key so if we // already have one, we can throw this away. - if ecdsa.Verify(pubKey.ToECDSA(), hash, - pSig.R, pSig.S) { - + if pSig.Verify(hash, pubKey) { aStr := addr.EncodeAddress() if _, ok := addrToSig[aStr]; !ok { addrToSig[aStr] = sig @@ -1424,14 +1420,14 @@ sigLoop: // KeyDB is an interface type provided to SignTxOutput, it encapsulates // any user state required to get the private keys for an address. type KeyDB interface { - GetKey(btcutil.Address) (*ecdsa.PrivateKey, bool, error) + GetKey(btcutil.Address) (*btcec.PrivateKey, bool, error) } -// KeyClosure implements KeyDB with a closure -type KeyClosure func(btcutil.Address) (*ecdsa.PrivateKey, bool, error) +// KeyClosure implements ScriptDB with a closure +type KeyClosure func(btcutil.Address) (*btcec.PrivateKey, bool, error) // GetKey implements KeyDB by returning the result of calling the closure -func (kc KeyClosure) GetKey(address btcutil.Address) (*ecdsa.PrivateKey, +func (kc KeyClosure) GetKey(address btcutil.Address) (*btcec.PrivateKey, bool, error) { return kc(address) } diff --git a/script_test.go b/script_test.go index b859fae6..ec097c57 100644 --- a/script_test.go +++ b/script_test.go @@ -6,11 +6,8 @@ package btcscript_test import ( "bytes" - "crypto/ecdsa" - "crypto/rand" "errors" "fmt" - "math/big" "testing" "github.com/conformal/btcec" @@ -2766,17 +2763,7 @@ var SigScriptTests = []TstSigScript{ // created for the MsgTxs in txTests, since they come from the blockchain // and we don't have the private keys. func TestSignatureScript(t *testing.T) { - privKey := &ecdsa.PrivateKey{ - PublicKey: ecdsa.PublicKey{ - Curve: btcec.S256(), - X: new(big.Int), - Y: new(big.Int), - }, - D: new(big.Int), - } - privKey.D.SetBytes(privKeyD) - privKey.PublicKey.X.SetBytes(pubkeyX) - privKey.PublicKey.Y.SetBytes(pubkeyY) + privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), privKeyD) nexttest: for i := range SigScriptTests { @@ -3272,18 +3259,18 @@ func checkScripts(msg string, tx *btcwire.MsgTx, idx int, } type addressToKey struct { - key *ecdsa.PrivateKey + key *btcec.PrivateKey compressed bool } func mkGetKey(keys map[string]addressToKey) btcscript.KeyDB { if keys == nil { - return btcscript.KeyClosure(func(addr btcutil.Address) (*ecdsa.PrivateKey, + return btcscript.KeyClosure(func(addr btcutil.Address) (*btcec.PrivateKey, bool, error) { return nil, false, errors.New("nope") }) } - return btcscript.KeyClosure(func(addr btcutil.Address) (*ecdsa.PrivateKey, + return btcscript.KeyClosure(func(addr btcutil.Address) (*btcec.PrivateKey, bool, error) { a2k, ok := keys[addr.EncodeAddress()] if !ok { @@ -3366,8 +3353,7 @@ func TestSignTxOutput(t *testing.T) { for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := ecdsa.GenerateKey(btcec.S256(), - rand.Reader) + key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) @@ -3404,8 +3390,7 @@ func TestSignTxOutput(t *testing.T) { for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := ecdsa.GenerateKey(btcec.S256(), - rand.Reader) + key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) @@ -3466,8 +3451,7 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := ecdsa.GenerateKey(btcec.S256(), - rand.Reader) + key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) @@ -3505,8 +3489,7 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := ecdsa.GenerateKey(btcec.S256(), - rand.Reader) + key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) @@ -3567,8 +3550,7 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := ecdsa.GenerateKey(btcec.S256(), - rand.Reader) + key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) @@ -3606,8 +3588,7 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := ecdsa.GenerateKey(btcec.S256(), - rand.Reader) + key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) @@ -3668,8 +3649,7 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := ecdsa.GenerateKey(btcec.S256(), - rand.Reader) + key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) @@ -3707,8 +3687,7 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := ecdsa.GenerateKey(btcec.S256(), - rand.Reader) + key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) @@ -3769,8 +3748,7 @@ func TestSignTxOutput(t *testing.T) { for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := ecdsa.GenerateKey(btcec.S256(), - rand.Reader) + key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) @@ -3827,8 +3805,7 @@ func TestSignTxOutput(t *testing.T) { for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := ecdsa.GenerateKey(btcec.S256(), - rand.Reader) + key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) @@ -3910,8 +3887,7 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := ecdsa.GenerateKey(btcec.S256(), - rand.Reader) + key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) @@ -3968,8 +3944,7 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := ecdsa.GenerateKey(btcec.S256(), - rand.Reader) + key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) @@ -4050,8 +4025,7 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := ecdsa.GenerateKey(btcec.S256(), - rand.Reader) + key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) @@ -4108,8 +4082,7 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := ecdsa.GenerateKey(btcec.S256(), - rand.Reader) + key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) @@ -4190,8 +4163,7 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := ecdsa.GenerateKey(btcec.S256(), - rand.Reader) + key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) @@ -4248,8 +4220,7 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := ecdsa.GenerateKey(btcec.S256(), - rand.Reader) + key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) @@ -4330,8 +4301,7 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key1, err := ecdsa.GenerateKey(btcec.S256(), - rand.Reader) + key1, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) @@ -4348,8 +4318,7 @@ func TestSignTxOutput(t *testing.T) { break } - key2, err := ecdsa.GenerateKey(btcec.S256(), - rand.Reader) + key2, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey 2 for %s: %v", msg, err) @@ -4409,8 +4378,7 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key1, err := ecdsa.GenerateKey(btcec.S256(), - rand.Reader) + key1, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) @@ -4427,8 +4395,7 @@ func TestSignTxOutput(t *testing.T) { break } - key2, err := ecdsa.GenerateKey(btcec.S256(), - rand.Reader) + key2, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey 2 for %s: %v", msg, err) @@ -4518,8 +4485,7 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key1, err := ecdsa.GenerateKey(btcec.S256(), - rand.Reader) + key1, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) @@ -4536,8 +4502,7 @@ func TestSignTxOutput(t *testing.T) { break } - key2, err := ecdsa.GenerateKey(btcec.S256(), - rand.Reader) + key2, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey 2 for %s: %v", msg, err) From a61c0f06cfde0909e99950e9f41d88a4d69e6aa2 Mon Sep 17 00:00:00 2001 From: Jonathan Gillham Date: Mon, 13 Oct 2014 13:47:44 +0100 Subject: [PATCH 155/174] Removed unnecessary signTxOutputCustomReader. --- script.go | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/script.go b/script.go index a1e86c07..4e0e165c 100644 --- a/script.go +++ b/script.go @@ -6,11 +6,9 @@ package btcscript import ( "bytes" - "crypto/rand" "encoding/binary" "errors" "fmt" - "io" "time" "github.com/conformal/btcec" @@ -1116,15 +1114,8 @@ func SignatureScript(tx *btcwire.MsgTx, idx int, subscript []byte, hashType SigH return NewScriptBuilder().AddData(sig).AddData(pkData).Script(), nil } -func signTxOutput(tx *btcwire.MsgTx, idx int, subScript []byte, hashType SigHashType, - key *btcec.PrivateKey) ([]byte, error) { - - return signTxOutputCustomReader(rand.Reader, tx, idx, subScript, - hashType, key) -} - -func signTxOutputCustomReader(reader io.Reader, tx *btcwire.MsgTx, idx int, - subScript []byte, hashType SigHashType, key *btcec.PrivateKey) ([]byte, error) { +func signTxOutput(tx *btcwire.MsgTx, idx int, subScript []byte, + hashType SigHashType, key *btcec.PrivateKey) ([]byte, error) { parsedScript, err := parseScript(subScript) if err != nil { return nil, fmt.Errorf("cannot parse output script: %v", err) From def35f2cd4ec47e2ae5e0edd2f49ff078ba22af2 Mon Sep 17 00:00:00 2001 From: David Hill Date: Mon, 8 Dec 2014 15:41:27 -0500 Subject: [PATCH 156/174] Sync Bitcoin Core tests. --- data/script_invalid.json | 585 +++++++++++++------------- data/script_valid.json | 868 ++++++++++++++++++++------------------- internal_test.go | 102 +++-- 3 files changed, 803 insertions(+), 752 deletions(-) diff --git a/data/script_invalid.json b/data/script_invalid.json index e3e1ccbf..75de4716 100644 --- a/data/script_invalid.json +++ b/data/script_invalid.json @@ -1,366 +1,377 @@ [ -["", "DEPTH", "Test the test: we should have an empty stack after scriptSig evaluation"], -[" ", "DEPTH", "and multiple spaces should not change that."], -[" ", "DEPTH"], -[" ", "DEPTH"], +["", "DEPTH", "P2SH,STRICTENC", "Test the test: we should have an empty stack after scriptSig evaluation"], +[" ", "DEPTH", "P2SH,STRICTENC", "and multiple spaces should not change that."], +[" ", "DEPTH", "P2SH,STRICTENC"], +[" ", "DEPTH", "P2SH,STRICTENC"], -["", ""], -["", "NOP"], -["", "NOP DEPTH"], -["NOP", ""], -["NOP", "DEPTH"], -["NOP","NOP"], -["NOP","NOP DEPTH"], +["", "", "P2SH,STRICTENC"], +["", "NOP", "P2SH,STRICTENC"], +["", "NOP DEPTH", "P2SH,STRICTENC"], +["NOP", "", "P2SH,STRICTENC"], +["NOP", "DEPTH", "P2SH,STRICTENC"], +["NOP","NOP", "P2SH,STRICTENC"], +["NOP","NOP DEPTH", "P2SH,STRICTENC"], -["DEPTH", ""], +["DEPTH", "", "P2SH,STRICTENC"], -["0x4c01","0x01 NOP", "PUSHDATA1 with not enough bytes"], -["0x4d0200ff","0x01 NOP", "PUSHDATA2 with not enough bytes"], -["0x4e03000000ffff","0x01 NOP", "PUSHDATA4 with not enough bytes"], +["0x4c01","0x01 NOP", "P2SH,STRICTENC", "PUSHDATA1 with not enough bytes"], +["0x4d0200ff","0x01 NOP", "P2SH,STRICTENC", "PUSHDATA2 with not enough bytes"], +["0x4e03000000ffff","0x01 NOP", "P2SH,STRICTENC", "PUSHDATA4 with not enough bytes"], -["1", "IF 0x50 ENDIF 1", "0x50 is reserved"], -["0x52", "0x5f ADD 0x60 EQUAL", "0x51 through 0x60 push 1 through 16 onto stack"], -["0","NOP"], -["1", "IF VER ELSE 1 ENDIF", "VER non-functional"], -["0", "IF VERIF ELSE 1 ENDIF", "VERIF illegal everywhere"], -["0", "IF ELSE 1 ELSE VERIF ENDIF", "VERIF illegal everywhere"], -["0", "IF VERNOTIF ELSE 1 ENDIF", "VERNOTIF illegal everywhere"], -["0", "IF ELSE 1 ELSE VERNOTIF ENDIF", "VERNOTIF illegal everywhere"], +["1", "IF 0x50 ENDIF 1", "P2SH,STRICTENC", "0x50 is reserved"], +["0x52", "0x5f ADD 0x60 EQUAL", "P2SH,STRICTENC", "0x51 through 0x60 push 1 through 16 onto stack"], +["0","NOP", "P2SH,STRICTENC"], +["1", "IF VER ELSE 1 ENDIF", "P2SH,STRICTENC", "VER non-functional"], +["0", "IF VERIF ELSE 1 ENDIF", "P2SH,STRICTENC", "VERIF illegal everywhere"], +["0", "IF ELSE 1 ELSE VERIF ENDIF", "P2SH,STRICTENC", "VERIF illegal everywhere"], +["0", "IF VERNOTIF ELSE 1 ENDIF", "P2SH,STRICTENC", "VERNOTIF illegal everywhere"], +["0", "IF ELSE 1 ELSE VERNOTIF ENDIF", "P2SH,STRICTENC", "VERNOTIF illegal everywhere"], -["1 IF", "1 ENDIF", "IF/ENDIF can't span scriptSig/scriptPubKey"], -["1 IF 0 ENDIF", "1 ENDIF"], -["1 ELSE 0 ENDIF", "1"], -["0 NOTIF", "123"], +["1 IF", "1 ENDIF", "P2SH,STRICTENC", "IF/ENDIF can't span scriptSig/scriptPubKey"], +["1 IF 0 ENDIF", "1 ENDIF", "P2SH,STRICTENC"], +["1 ELSE 0 ENDIF", "1", "P2SH,STRICTENC"], +["0 NOTIF", "123", "P2SH,STRICTENC"], -["0", "DUP IF ENDIF"], -["0", "IF 1 ENDIF"], -["0", "DUP IF ELSE ENDIF"], -["0", "IF 1 ELSE ENDIF"], -["0", "NOTIF ELSE 1 ENDIF"], +["0", "DUP IF ENDIF", "P2SH,STRICTENC"], +["0", "IF 1 ENDIF", "P2SH,STRICTENC"], +["0", "DUP IF ELSE ENDIF", "P2SH,STRICTENC"], +["0", "IF 1 ELSE ENDIF", "P2SH,STRICTENC"], +["0", "NOTIF ELSE 1 ENDIF", "P2SH,STRICTENC"], -["0 1", "IF IF 1 ELSE 0 ENDIF ENDIF"], -["0 0", "IF IF 1 ELSE 0 ENDIF ENDIF"], -["1 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], -["0 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], +["0 1", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"], +["0 0", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"], +["1 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"], +["0 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"], -["0 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF"], -["0 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF"], -["1 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], -["0 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], +["0 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"], +["0 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"], +["1 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"], +["0 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"], -["1", "IF RETURN ELSE ELSE 1 ENDIF", "Multiple ELSEs"], -["1", "IF 1 ELSE ELSE RETURN ENDIF"], +["1", "IF RETURN ELSE ELSE 1 ENDIF", "P2SH,STRICTENC", "Multiple ELSEs"], +["1", "IF 1 ELSE ELSE RETURN ENDIF", "P2SH,STRICTENC"], -["1", "ENDIF", "Malformed IF/ELSE/ENDIF sequence"], -["1", "ELSE ENDIF"], -["1", "ENDIF ELSE"], -["1", "ENDIF ELSE IF"], -["1", "IF ELSE ENDIF ELSE"], -["1", "IF ELSE ENDIF ELSE ENDIF"], -["1", "IF ENDIF ENDIF"], -["1", "IF ELSE ELSE ENDIF ENDIF"], +["1", "ENDIF", "P2SH,STRICTENC", "Malformed IF/ELSE/ENDIF sequence"], +["1", "ELSE ENDIF", "P2SH,STRICTENC"], +["1", "ENDIF ELSE", "P2SH,STRICTENC"], +["1", "ENDIF ELSE IF", "P2SH,STRICTENC"], +["1", "IF ELSE ENDIF ELSE", "P2SH,STRICTENC"], +["1", "IF ELSE ENDIF ELSE ENDIF", "P2SH,STRICTENC"], +["1", "IF ENDIF ENDIF", "P2SH,STRICTENC"], +["1", "IF ELSE ELSE ENDIF ENDIF", "P2SH,STRICTENC"], -["1", "RETURN"], -["1", "DUP IF RETURN ENDIF"], +["1", "RETURN", "P2SH,STRICTENC"], +["1", "DUP IF RETURN ENDIF", "P2SH,STRICTENC"], -["1", "RETURN 'data'", "canonical prunable txout format"], -["0 IF", "RETURN ENDIF 1", "still prunable because IF/ENDIF can't span scriptSig/scriptPubKey"], +["1", "RETURN 'data'", "P2SH,STRICTENC", "canonical prunable txout format"], +["0 IF", "RETURN ENDIF 1", "P2SH,STRICTENC", "still prunable because IF/ENDIF can't span scriptSig/scriptPubKey"], -["0", "VERIFY 1"], -["1", "VERIFY"], -["1", "VERIFY 0"], +["0", "VERIFY 1", "P2SH,STRICTENC"], +["1", "VERIFY", "P2SH,STRICTENC"], +["1", "VERIFY 0", "P2SH,STRICTENC"], -["1 TOALTSTACK", "FROMALTSTACK 1", "alt stack not shared between sig/pubkey"], +["1 TOALTSTACK", "FROMALTSTACK 1", "P2SH,STRICTENC", "alt stack not shared between sig/pubkey"], -["IFDUP", "DEPTH 0 EQUAL"], -["DROP", "DEPTH 0 EQUAL"], -["DUP", "DEPTH 0 EQUAL"], -["1", "DUP 1 ADD 2 EQUALVERIFY 0 EQUAL"], -["NOP", "NIP"], -["NOP", "1 NIP"], -["NOP", "1 0 NIP"], -["NOP", "OVER 1"], -["1", "OVER"], -["0 1", "OVER DEPTH 3 EQUALVERIFY"], -["19 20 21", "PICK 19 EQUALVERIFY DEPTH 2 EQUAL"], -["NOP", "0 PICK"], -["1", "-1 PICK"], -["19 20 21", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL"], -["19 20 21", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL"], -["19 20 21", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL"], -["NOP", "0 ROLL"], -["1", "-1 ROLL"], -["19 20 21", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL"], -["19 20 21", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL"], -["19 20 21", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL"], -["NOP", "ROT 1"], -["NOP", "1 ROT 1"], -["NOP", "1 2 ROT 1"], -["NOP", "0 1 2 ROT"], -["NOP", "SWAP 1"], -["1", "SWAP 1"], -["0 1", "SWAP 1 EQUALVERIFY"], -["NOP", "TUCK 1"], -["1", "TUCK 1"], -["1 0", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP"], -["NOP", "2DUP 1"], -["1", "2DUP 1"], -["NOP", "3DUP 1"], -["1", "3DUP 1"], -["1 2", "3DUP 1"], -["NOP", "2OVER 1"], -["1", "2 3 2OVER 1"], -["NOP", "2SWAP 1"], -["1", "2 3 2SWAP 1"], +["IFDUP", "DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["DROP", "DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["DUP", "DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["1", "DUP 1 ADD 2 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC"], +["NOP", "NIP", "P2SH,STRICTENC"], +["NOP", "1 NIP", "P2SH,STRICTENC"], +["NOP", "1 0 NIP", "P2SH,STRICTENC"], +["NOP", "OVER 1", "P2SH,STRICTENC"], +["1", "OVER", "P2SH,STRICTENC"], +["0 1", "OVER DEPTH 3 EQUALVERIFY", "P2SH,STRICTENC"], +["19 20 21", "PICK 19 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"], +["NOP", "0 PICK", "P2SH,STRICTENC"], +["1", "-1 PICK", "P2SH,STRICTENC"], +["19 20 21", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC"], +["19 20 21", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC"], +["19 20 21", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC"], +["NOP", "0 ROLL", "P2SH,STRICTENC"], +["1", "-1 ROLL", "P2SH,STRICTENC"], +["19 20 21", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"], +["19 20 21", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"], +["19 20 21", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"], +["NOP", "ROT 1", "P2SH,STRICTENC"], +["NOP", "1 ROT 1", "P2SH,STRICTENC"], +["NOP", "1 2 ROT 1", "P2SH,STRICTENC"], +["NOP", "0 1 2 ROT", "P2SH,STRICTENC"], +["NOP", "SWAP 1", "P2SH,STRICTENC"], +["1", "SWAP 1", "P2SH,STRICTENC"], +["0 1", "SWAP 1 EQUALVERIFY", "P2SH,STRICTENC"], +["NOP", "TUCK 1", "P2SH,STRICTENC"], +["1", "TUCK 1", "P2SH,STRICTENC"], +["1 0", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP", "P2SH,STRICTENC"], +["NOP", "2DUP 1", "P2SH,STRICTENC"], +["1", "2DUP 1", "P2SH,STRICTENC"], +["NOP", "3DUP 1", "P2SH,STRICTENC"], +["1", "3DUP 1", "P2SH,STRICTENC"], +["1 2", "3DUP 1", "P2SH,STRICTENC"], +["NOP", "2OVER 1", "P2SH,STRICTENC"], +["1", "2 3 2OVER 1", "P2SH,STRICTENC"], +["NOP", "2SWAP 1", "P2SH,STRICTENC"], +["1", "2 3 2SWAP 1", "P2SH,STRICTENC"], -["'a' 'b'", "CAT", "CAT disabled"], -["'a' 'b' 0", "IF CAT ELSE 1 ENDIF", "CAT disabled"], -["'abc' 1 1", "SUBSTR", "SUBSTR disabled"], -["'abc' 1 1 0", "IF SUBSTR ELSE 1 ENDIF", "SUBSTR disabled"], -["'abc' 2 0", "IF LEFT ELSE 1 ENDIF", "LEFT disabled"], -["'abc' 2 0", "IF RIGHT ELSE 1 ENDIF", "RIGHT disabled"], +["'a' 'b'", "CAT", "P2SH,STRICTENC", "CAT disabled"], +["'a' 'b' 0", "IF CAT ELSE 1 ENDIF", "P2SH,STRICTENC", "CAT disabled"], +["'abc' 1 1", "SUBSTR", "P2SH,STRICTENC", "SUBSTR disabled"], +["'abc' 1 1 0", "IF SUBSTR ELSE 1 ENDIF", "P2SH,STRICTENC", "SUBSTR disabled"], +["'abc' 2 0", "IF LEFT ELSE 1 ENDIF", "P2SH,STRICTENC", "LEFT disabled"], +["'abc' 2 0", "IF RIGHT ELSE 1 ENDIF", "P2SH,STRICTENC", "RIGHT disabled"], -["NOP", "SIZE 1"], +["NOP", "SIZE 1", "P2SH,STRICTENC"], -["'abc'", "IF INVERT ELSE 1 ENDIF", "INVERT disabled"], -["1 2 0 IF AND ELSE 1 ENDIF", "NOP", "AND disabled"], -["1 2 0 IF OR ELSE 1 ENDIF", "NOP", "OR disabled"], -["1 2 0 IF XOR ELSE 1 ENDIF", "NOP", "XOR disabled"], -["2 0 IF 2MUL ELSE 1 ENDIF", "NOP", "2MUL disabled"], -["2 0 IF 2DIV ELSE 1 ENDIF", "NOP", "2DIV disabled"], -["2 2 0 IF MUL ELSE 1 ENDIF", "NOP", "MUL disabled"], -["2 2 0 IF DIV ELSE 1 ENDIF", "NOP", "DIV disabled"], -["2 2 0 IF MOD ELSE 1 ENDIF", "NOP", "MOD disabled"], -["2 2 0 IF LSHIFT ELSE 1 ENDIF", "NOP", "LSHIFT disabled"], -["2 2 0 IF RSHIFT ELSE 1 ENDIF", "NOP", "RSHIFT disabled"], +["'abc'", "IF INVERT ELSE 1 ENDIF", "P2SH,STRICTENC", "INVERT disabled"], +["1 2 0 IF AND ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "AND disabled"], +["1 2 0 IF OR ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "OR disabled"], +["1 2 0 IF XOR ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "XOR disabled"], +["2 0 IF 2MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "2MUL disabled"], +["2 0 IF 2DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "2DIV disabled"], +["2 2 0 IF MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "MUL disabled"], +["2 2 0 IF DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DIV disabled"], +["2 2 0 IF MOD ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "MOD disabled"], +["2 2 0 IF LSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "LSHIFT disabled"], +["2 2 0 IF RSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "RSHIFT disabled"], -["0 1","EQUAL"], -["1 1 ADD", "0 EQUAL"], -["11 1 ADD 12 SUB", "11 EQUAL"], +["0 1","EQUAL", "P2SH,STRICTENC"], +["1 1 ADD", "0 EQUAL", "P2SH,STRICTENC"], +["11 1 ADD 12 SUB", "11 EQUAL", "P2SH,STRICTENC"], -["2147483648 0 ADD", "NOP", "arithmetic operands must be in range [-2^31...2^31] "], -["-2147483648 0 ADD", "NOP", "arithmetic operands must be in range [-2^31...2^31] "], -["2147483647 DUP ADD", "4294967294 NUMEQUAL", "NUMEQUAL must be in numeric range"], -["'abcdef' NOT", "0 EQUAL", "NOT is an arithmetic operand"], +["2147483648 0 ADD", "NOP", "P2SH,STRICTENC", "arithmetic operands must be in range [-2^31...2^31] "], +["-2147483648 0 ADD", "NOP", "P2SH,STRICTENC", "arithmetic operands must be in range [-2^31...2^31] "], +["2147483647 DUP ADD", "4294967294 NUMEQUAL", "P2SH,STRICTENC", "NUMEQUAL must be in numeric range"], +["'abcdef' NOT", "0 EQUAL", "P2SH,STRICTENC", "NOT is an arithmetic operand"], -["2 DUP MUL", "4 EQUAL", "disabled"], -["2 DUP DIV", "1 EQUAL", "disabled"], -["2 2MUL", "4 EQUAL", "disabled"], -["2 2DIV", "1 EQUAL", "disabled"], -["7 3 MOD", "1 EQUAL", "disabled"], -["2 2 LSHIFT", "8 EQUAL", "disabled"], -["2 1 RSHIFT", "1 EQUAL", "disabled"], +["2 DUP MUL", "4 EQUAL", "P2SH,STRICTENC", "disabled"], +["2 DUP DIV", "1 EQUAL", "P2SH,STRICTENC", "disabled"], +["2 2MUL", "4 EQUAL", "P2SH,STRICTENC", "disabled"], +["2 2DIV", "1 EQUAL", "P2SH,STRICTENC", "disabled"], +["7 3 MOD", "1 EQUAL", "P2SH,STRICTENC", "disabled"], +["2 2 LSHIFT", "8 EQUAL", "P2SH,STRICTENC", "disabled"], +["2 1 RSHIFT", "1 EQUAL", "P2SH,STRICTENC", "disabled"], -["1","NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL"], -["'NOP_1_to_10' NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL"], +["1","NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC"], +["'NOP_1_to_10' NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC"], -["0x50","1", "opcode 0x50 is reserved"], -["1", "IF 0xba ELSE 1 ENDIF", "opcodes above NOP10 invalid if executed"], -["1", "IF 0xbb ELSE 1 ENDIF"], -["1", "IF 0xbc ELSE 1 ENDIF"], -["1", "IF 0xbd ELSE 1 ENDIF"], -["1", "IF 0xbe ELSE 1 ENDIF"], -["1", "IF 0xbf ELSE 1 ENDIF"], -["1", "IF 0xc0 ELSE 1 ENDIF"], -["1", "IF 0xc1 ELSE 1 ENDIF"], -["1", "IF 0xc2 ELSE 1 ENDIF"], -["1", "IF 0xc3 ELSE 1 ENDIF"], -["1", "IF 0xc4 ELSE 1 ENDIF"], -["1", "IF 0xc5 ELSE 1 ENDIF"], -["1", "IF 0xc6 ELSE 1 ENDIF"], -["1", "IF 0xc7 ELSE 1 ENDIF"], -["1", "IF 0xc8 ELSE 1 ENDIF"], -["1", "IF 0xc9 ELSE 1 ENDIF"], -["1", "IF 0xca ELSE 1 ENDIF"], -["1", "IF 0xcb ELSE 1 ENDIF"], -["1", "IF 0xcc ELSE 1 ENDIF"], -["1", "IF 0xcd ELSE 1 ENDIF"], -["1", "IF 0xce ELSE 1 ENDIF"], -["1", "IF 0xcf ELSE 1 ENDIF"], -["1", "IF 0xd0 ELSE 1 ENDIF"], -["1", "IF 0xd1 ELSE 1 ENDIF"], -["1", "IF 0xd2 ELSE 1 ENDIF"], -["1", "IF 0xd3 ELSE 1 ENDIF"], -["1", "IF 0xd4 ELSE 1 ENDIF"], -["1", "IF 0xd5 ELSE 1 ENDIF"], -["1", "IF 0xd6 ELSE 1 ENDIF"], -["1", "IF 0xd7 ELSE 1 ENDIF"], -["1", "IF 0xd8 ELSE 1 ENDIF"], -["1", "IF 0xd9 ELSE 1 ENDIF"], -["1", "IF 0xda ELSE 1 ENDIF"], -["1", "IF 0xdb ELSE 1 ENDIF"], -["1", "IF 0xdc ELSE 1 ENDIF"], -["1", "IF 0xdd ELSE 1 ENDIF"], -["1", "IF 0xde ELSE 1 ENDIF"], -["1", "IF 0xdf ELSE 1 ENDIF"], -["1", "IF 0xe0 ELSE 1 ENDIF"], -["1", "IF 0xe1 ELSE 1 ENDIF"], -["1", "IF 0xe2 ELSE 1 ENDIF"], -["1", "IF 0xe3 ELSE 1 ENDIF"], -["1", "IF 0xe4 ELSE 1 ENDIF"], -["1", "IF 0xe5 ELSE 1 ENDIF"], -["1", "IF 0xe6 ELSE 1 ENDIF"], -["1", "IF 0xe7 ELSE 1 ENDIF"], -["1", "IF 0xe8 ELSE 1 ENDIF"], -["1", "IF 0xe9 ELSE 1 ENDIF"], -["1", "IF 0xea ELSE 1 ENDIF"], -["1", "IF 0xeb ELSE 1 ENDIF"], -["1", "IF 0xec ELSE 1 ENDIF"], -["1", "IF 0xed ELSE 1 ENDIF"], -["1", "IF 0xee ELSE 1 ENDIF"], -["1", "IF 0xef ELSE 1 ENDIF"], -["1", "IF 0xf0 ELSE 1 ENDIF"], -["1", "IF 0xf1 ELSE 1 ENDIF"], -["1", "IF 0xf2 ELSE 1 ENDIF"], -["1", "IF 0xf3 ELSE 1 ENDIF"], -["1", "IF 0xf4 ELSE 1 ENDIF"], -["1", "IF 0xf5 ELSE 1 ENDIF"], -["1", "IF 0xf6 ELSE 1 ENDIF"], -["1", "IF 0xf7 ELSE 1 ENDIF"], -["1", "IF 0xf8 ELSE 1 ENDIF"], -["1", "IF 0xf9 ELSE 1 ENDIF"], -["1", "IF 0xfa ELSE 1 ENDIF"], -["1", "IF 0xfb ELSE 1 ENDIF"], -["1", "IF 0xfc ELSE 1 ENDIF"], -["1", "IF 0xfd ELSE 1 ENDIF"], -["1", "IF 0xfe ELSE 1 ENDIF"], -["1", "IF 0xff ELSE 1 ENDIF"], +["0x50","1", "P2SH,STRICTENC", "opcode 0x50 is reserved"], +["1", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "opcodes above NOP10 invalid if executed"], +["1", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xc0 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xc4 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xc5 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xc6 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xc7 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xc8 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xc9 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xca ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xcb ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xcc ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xcd ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xce ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xcf ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xd0 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xd1 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xd2 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xd3 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xd4 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xd5 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xd6 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xd7 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xd8 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xd9 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xda ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xdb ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xdc ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xdd ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xde ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xdf ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xe0 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xe1 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xe2 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xe3 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xe4 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xe5 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xe6 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xe7 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xe8 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xe9 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xea ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xeb ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xec ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xed ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xee ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xef ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xf0 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xf1 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xf2 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xf3 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xf4 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xf5 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xf6 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xf7 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xf8 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xf9 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xfa ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xfb ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xfc ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xfd ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xfe ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 0xff ELSE 1 ENDIF", "P2SH,STRICTENC"], -["1 IF 1 ELSE", "0xff ENDIF", "invalid because scriptSig and scriptPubKey are processed separately"], +["1 IF 1 ELSE", "0xff ENDIF", "P2SH,STRICTENC", "invalid because scriptSig and scriptPubKey are processed separately"], -["NOP", "RIPEMD160"], -["NOP", "SHA1"], -["NOP", "SHA256"], -["NOP", "HASH160"], -["NOP", "HASH256"], +["NOP", "RIPEMD160", "P2SH,STRICTENC"], +["NOP", "SHA1", "P2SH,STRICTENC"], +["NOP", "SHA256", "P2SH,STRICTENC"], +["NOP", "HASH160", "P2SH,STRICTENC"], +["NOP", "HASH256", "P2SH,STRICTENC"], ["NOP", "'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'", +"P2SH,STRICTENC", ">520 byte push"], ["0", "IF 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' ENDIF 1", +"P2SH,STRICTENC", ">520 byte push in non-executed IF branch"], ["1", "0x61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", +"P2SH,STRICTENC", ">201 opcodes executed. 0x61 is NOP"], ["0", "IF 0x6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161 ENDIF 1", +"P2SH,STRICTENC", ">201 opcodes including non-executed IF branch. 0x61 is NOP"], ["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", "1 2 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"P2SH,STRICTENC", ">1,000 stack size (0x6f is 3DUP)"], ["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", "1 TOALTSTACK 2 TOALTSTACK 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"P2SH,STRICTENC", ">1,000 stack+altstack size"], ["NOP", "0 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f 2DUP 0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", +"P2SH,STRICTENC", "10,001-byte scriptPubKey"], -["NOP1","NOP10"], +["NOP1","NOP10", "P2SH,STRICTENC"], -["1","VER", "OP_VER is reserved"], -["1","VERIF", "OP_VERIF is reserved"], -["1","VERNOTIF", "OP_VERNOTIF is reserved"], -["1","RESERVED", "OP_RESERVED is reserved"], -["1","RESERVED1", "OP_RESERVED1 is reserved"], -["1","RESERVED2", "OP_RESERVED2 is reserved"], -["1","0xba", "0xba == OP_NOP10 + 1"], +["1","VER", "P2SH,STRICTENC", "OP_VER is reserved"], +["1","VERIF", "P2SH,STRICTENC", "OP_VERIF is reserved"], +["1","VERNOTIF", "P2SH,STRICTENC", "OP_VERNOTIF is reserved"], +["1","RESERVED", "P2SH,STRICTENC", "OP_RESERVED is reserved"], +["1","RESERVED1", "P2SH,STRICTENC", "OP_RESERVED1 is reserved"], +["1","RESERVED2", "P2SH,STRICTENC", "OP_RESERVED2 is reserved"], +["1","0xba", "P2SH,STRICTENC", "0xba == OP_NOP10 + 1"], -["2147483648", "1ADD 1", "We cannot do math on 5-byte integers"], -["2147483648", "NEGATE 1", "We cannot do math on 5-byte integers"], -["-2147483648", "1ADD 1", "Because we use a sign bit, -2147483648 is also 5 bytes"], -["2147483647", "1ADD 1SUB 1", "We cannot do math on 5-byte integers, even if the result is 4-bytes"], -["2147483648", "1SUB 1", "We cannot do math on 5-byte integers, even if the result is 4-bytes"], +["2147483648", "1ADD 1", "P2SH,STRICTENC", "We cannot do math on 5-byte integers"], +["2147483648", "NEGATE 1", "P2SH,STRICTENC", "We cannot do math on 5-byte integers"], +["-2147483648", "1ADD 1", "P2SH,STRICTENC", "Because we use a sign bit, -2147483648 is also 5 bytes"], +["2147483647", "1ADD 1SUB 1", "P2SH,STRICTENC", "We cannot do math on 5-byte integers, even if the result is 4-bytes"], +["2147483648", "1SUB 1", "P2SH,STRICTENC", "We cannot do math on 5-byte integers, even if the result is 4-bytes"], -["2147483648 1", "BOOLOR 1", "We cannot do BOOLOR on 5-byte integers (but we can still do IF etc)"], -["2147483648 1", "BOOLAND 1", "We cannot do BOOLAND on 5-byte integers"], +["2147483648 1", "BOOLOR 1", "P2SH,STRICTENC", "We cannot do BOOLOR on 5-byte integers (but we can still do IF etc)"], +["2147483648 1", "BOOLAND 1", "P2SH,STRICTENC", "We cannot do BOOLAND on 5-byte integers"], -["1", "1 ENDIF", "ENDIF without IF"], -["1", "IF 1", "IF without ENDIF"], -["1 IF 1", "ENDIF", "IFs don't carry over"], +["1", "1 ENDIF", "P2SH,STRICTENC", "ENDIF without IF"], +["1", "IF 1", "P2SH,STRICTENC", "IF without ENDIF"], +["1 IF 1", "ENDIF", "P2SH,STRICTENC", "IFs don't carry over"], -["NOP", "IF 1 ENDIF", "The following tests check the if(stack.size() < N) tests in each opcode"], -["NOP", "NOTIF 1 ENDIF", "They are here to catch copy-and-paste errors"], -["NOP", "VERIFY 1", "Most of them are duplicated elsewhere,"], +["NOP", "IF 1 ENDIF", "P2SH,STRICTENC", "The following tests check the if(stack.size() < N) tests in each opcode"], +["NOP", "NOTIF 1 ENDIF", "P2SH,STRICTENC", "They are here to catch copy-and-paste errors"], +["NOP", "VERIFY 1", "P2SH,STRICTENC", "Most of them are duplicated elsewhere,"], -["NOP", "TOALTSTACK 1", "but, hey, more is always better, right?"], -["1", "FROMALTSTACK"], -["1", "2DROP 1"], -["1", "2DUP"], -["1 1", "3DUP"], -["1 1 1", "2OVER"], -["1 1 1 1 1", "2ROT"], -["1 1 1", "2SWAP"], -["NOP", "IFDUP 1"], -["NOP", "DROP 1"], -["NOP", "DUP 1"], -["1", "NIP"], -["1", "OVER"], -["1 1 1 3", "PICK"], -["0", "PICK 1"], -["1 1 1 3", "ROLL"], -["0", "ROLL 1"], -["1 1", "ROT"], -["1", "SWAP"], -["1", "TUCK"], +["NOP", "TOALTSTACK 1", "P2SH,STRICTENC", "but, hey, more is always better, right?"], +["1", "FROMALTSTACK", "P2SH,STRICTENC"], +["1", "2DROP 1", "P2SH,STRICTENC"], +["1", "2DUP", "P2SH,STRICTENC"], +["1 1", "3DUP", "P2SH,STRICTENC"], +["1 1 1", "2OVER", "P2SH,STRICTENC"], +["1 1 1 1 1", "2ROT", "P2SH,STRICTENC"], +["1 1 1", "2SWAP", "P2SH,STRICTENC"], +["NOP", "IFDUP 1", "P2SH,STRICTENC"], +["NOP", "DROP 1", "P2SH,STRICTENC"], +["NOP", "DUP 1", "P2SH,STRICTENC"], +["1", "NIP", "P2SH,STRICTENC"], +["1", "OVER", "P2SH,STRICTENC"], +["1 1 1 3", "PICK", "P2SH,STRICTENC"], +["0", "PICK 1", "P2SH,STRICTENC"], +["1 1 1 3", "ROLL", "P2SH,STRICTENC"], +["0", "ROLL 1", "P2SH,STRICTENC"], +["1 1", "ROT", "P2SH,STRICTENC"], +["1", "SWAP", "P2SH,STRICTENC"], +["1", "TUCK", "P2SH,STRICTENC"], -["NOP", "SIZE 1"], +["NOP", "SIZE 1", "P2SH,STRICTENC"], -["1", "EQUAL 1"], -["1", "EQUALVERIFY 1"], +["1", "EQUAL 1", "P2SH,STRICTENC"], +["1", "EQUALVERIFY 1", "P2SH,STRICTENC"], -["NOP", "1ADD 1"], -["NOP", "1SUB 1"], -["NOP", "NEGATE 1"], -["NOP", "ABS 1"], -["NOP", "NOT 1"], -["NOP", "0NOTEQUAL 1"], +["NOP", "1ADD 1", "P2SH,STRICTENC"], +["NOP", "1SUB 1", "P2SH,STRICTENC"], +["NOP", "NEGATE 1", "P2SH,STRICTENC"], +["NOP", "ABS 1", "P2SH,STRICTENC"], +["NOP", "NOT 1", "P2SH,STRICTENC"], +["NOP", "0NOTEQUAL 1", "P2SH,STRICTENC"], -["1", "ADD"], -["1", "SUB"], -["1", "BOOLAND"], -["1", "BOOLOR"], -["1", "NUMEQUAL"], -["1", "NUMEQUALVERIFY 1"], -["1", "NUMNOTEQUAL"], -["1", "LESSTHAN"], -["1", "GREATERTHAN"], -["1", "LESSTHANOREQUAL"], -["1", "GREATERTHANOREQUAL"], -["1", "MIN"], -["1", "MAX"], -["1 1", "WITHIN"], +["1", "ADD", "P2SH,STRICTENC"], +["1", "SUB", "P2SH,STRICTENC"], +["1", "BOOLAND", "P2SH,STRICTENC"], +["1", "BOOLOR", "P2SH,STRICTENC"], +["1", "NUMEQUAL", "P2SH,STRICTENC"], +["1", "NUMEQUALVERIFY 1", "P2SH,STRICTENC"], +["1", "NUMNOTEQUAL", "P2SH,STRICTENC"], +["1", "LESSTHAN", "P2SH,STRICTENC"], +["1", "GREATERTHAN", "P2SH,STRICTENC"], +["1", "LESSTHANOREQUAL", "P2SH,STRICTENC"], +["1", "GREATERTHANOREQUAL", "P2SH,STRICTENC"], +["1", "MIN", "P2SH,STRICTENC"], +["1", "MAX", "P2SH,STRICTENC"], +["1 1", "WITHIN", "P2SH,STRICTENC"], -["NOP", "RIPEMD160 1"], -["NOP", "SHA1 1"], -["NOP", "SHA256 1"], -["NOP", "HASH160 1"], -["NOP", "HASH256 1"], +["NOP", "RIPEMD160 1", "P2SH,STRICTENC"], +["NOP", "SHA1 1", "P2SH,STRICTENC"], +["NOP", "SHA256 1", "P2SH,STRICTENC"], +["NOP", "HASH160 1", "P2SH,STRICTENC"], +["NOP", "HASH256 1", "P2SH,STRICTENC"], ["", "0 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG", +"P2SH,STRICTENC", "202 CHECKMULTISIGS, fails due to 201 op limit"], ["1", -"0 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY"], +"0 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY", +"P2SH,STRICTENC"], ["", "NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG", +"P2SH,STRICTENC", "Fails due to 201 sig op limit"], ["1", -"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY"], +"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY", +"P2SH,STRICTENC"], -["0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21", "21 CHECKMULTISIG 1", "nPubKeys > 20"], -["0 'sig' 1 0", "CHECKMULTISIG 1", "nSigs > nPubKeys"], +["0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21", "21 CHECKMULTISIG 1", "P2SH,STRICTENC", "nPubKeys > 20"], +["0 'sig' 1 0", "CHECKMULTISIG 1", "P2SH,STRICTENC", "nSigs > nPubKeys"], -["NOP 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "Tests for Script.IsPushOnly()"], -["NOP1 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL"], +["NOP 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "Tests for Script.IsPushOnly()"], +["NOP1 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC"], -["0 0x01 0x50", "HASH160 0x14 0xece424a6bb6ddf4db592c0faed60685047a361b1 EQUAL", "OP_RESERVED in P2SH should fail"], -["0 0x01 VER", "HASH160 0x14 0x0f4d7845db968f2a81b530b6f3c1d6246d4c7e01 EQUAL", "OP_VER in P2SH should fail"], +["0 0x01 0x50", "HASH160 0x14 0xece424a6bb6ddf4db592c0faed60685047a361b1 EQUAL", "P2SH,STRICTENC", "OP_RESERVED in P2SH should fail"], +["0 0x01 VER", "HASH160 0x14 0x0f4d7845db968f2a81b530b6f3c1d6246d4c7e01 EQUAL", "P2SH,STRICTENC", "OP_VER in P2SH should fail"], -["0x00", "'00' EQUAL", "Basic OP_0 execution"] +["0x00", "'00' EQUAL", "P2SH,STRICTENC", "Basic OP_0 execution"] ] diff --git a/data/script_valid.json b/data/script_valid.json index 082c65ef..c1db4c60 100644 --- a/data/script_valid.json +++ b/data/script_valid.json @@ -1,510 +1,522 @@ [ -["", "DEPTH 0 EQUAL", "Test the test: we should have an empty stack after scriptSig evaluation"], -[" ", "DEPTH 0 EQUAL", "and multiple spaces should not change that."], -[" ", "DEPTH 0 EQUAL"], -[" ", "DEPTH 0 EQUAL"], -["1 2", "2 EQUALVERIFY 1 EQUAL", "Similarly whitespace around and between symbols"], -["1 2", "2 EQUALVERIFY 1 EQUAL"], -[" 1 2", "2 EQUALVERIFY 1 EQUAL"], -["1 2 ", "2 EQUALVERIFY 1 EQUAL"], -[" 1 2 ", "2 EQUALVERIFY 1 EQUAL"], +["", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "Test the test: we should have an empty stack after scriptSig evaluation"], +[" ", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "and multiple spaces should not change that."], +[" ", "DEPTH 0 EQUAL", "P2SH,STRICTENC"], +[" ", "DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["1 2", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "Similarly whitespace around and between symbols"], +["1 2", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC"], +[" 1 2", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC"], +["1 2 ", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC"], +[" 1 2 ", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC"], -["1", ""], -["0x02 0x01 0x00", "", "all bytes are significant, not only the last one"], -["0x09 0x00000000 0x00000000 0x10", "", "equals zero when cast to Int64"], +["1", "", "P2SH,STRICTENC"], +["0x02 0x01 0x00", "", "P2SH,STRICTENC", "all bytes are significant, not only the last one"], +["0x09 0x00000000 0x00000000 0x10", "", "P2SH,STRICTENC", "equals zero when cast to Int64"], -["0x01 0x0b", "11 EQUAL", "push 1 byte"], -["0x02 0x417a", "'Az' EQUAL"], +["0x01 0x0b", "11 EQUAL", "P2SH,STRICTENC", "push 1 byte"], +["0x02 0x417a", "'Az' EQUAL", "P2SH,STRICTENC"], ["0x4b 0x417a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a", - "'Azzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' EQUAL", "push 75 bytes"], + "'Azzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' EQUAL", "P2SH,STRICTENC", "push 75 bytes"], -["0x4c 0x01 0x07","7 EQUAL", "0x4c is OP_PUSHDATA1"], -["0x4d 0x0100 0x08","8 EQUAL", "0x4d is OP_PUSHDATA2"], -["0x4e 0x01000000 0x09","9 EQUAL", "0x4e is OP_PUSHDATA4"], +["0x4c 0x01 0x07","7 EQUAL", "P2SH,STRICTENC", "0x4c is OP_PUSHDATA1"], +["0x4d 0x0100 0x08","8 EQUAL", "P2SH,STRICTENC", "0x4d is OP_PUSHDATA2"], +["0x4e 0x01000000 0x09","9 EQUAL", "P2SH,STRICTENC", "0x4e is OP_PUSHDATA4"], -["0x4c 0x00","0 EQUAL"], -["0x4d 0x0000","0 EQUAL"], -["0x4e 0x00000000","0 EQUAL"], -["0x4f 1000 ADD","999 EQUAL"], -["0", "IF 0x50 ENDIF 1", "0x50 is reserved (ok if not executed)"], -["0x51", "0x5f ADD 0x60 EQUAL", "0x51 through 0x60 push 1 through 16 onto stack"], -["1","NOP"], -["0", "IF VER ELSE 1 ENDIF", "VER non-functional (ok if not executed)"], -["0", "IF RESERVED RESERVED1 RESERVED2 ELSE 1 ENDIF", "RESERVED ok in un-executed IF"], +["0x4c 0x00","0 EQUAL", "P2SH,STRICTENC"], +["0x4d 0x0000","0 EQUAL", "P2SH,STRICTENC"], +["0x4e 0x00000000","0 EQUAL", "P2SH,STRICTENC"], +["0x4f 1000 ADD","999 EQUAL", "P2SH,STRICTENC"], +["0", "IF 0x50 ENDIF 1", "P2SH,STRICTENC", "0x50 is reserved (ok if not executed)"], +["0x51", "0x5f ADD 0x60 EQUAL", "P2SH,STRICTENC", "0x51 through 0x60 push 1 through 16 onto stack"], +["1","NOP", "P2SH,STRICTENC"], +["0", "IF VER ELSE 1 ENDIF", "P2SH,STRICTENC", "VER non-functional (ok if not executed)"], +["0", "IF RESERVED RESERVED1 RESERVED2 ELSE 1 ENDIF", "P2SH,STRICTENC", "RESERVED ok in un-executed IF"], -["1", "DUP IF ENDIF"], -["1", "IF 1 ENDIF"], -["1", "DUP IF ELSE ENDIF"], -["1", "IF 1 ELSE ENDIF"], -["0", "IF ELSE 1 ENDIF"], +["1", "DUP IF ENDIF", "P2SH,STRICTENC"], +["1", "IF 1 ENDIF", "P2SH,STRICTENC"], +["1", "DUP IF ELSE ENDIF", "P2SH,STRICTENC"], +["1", "IF 1 ELSE ENDIF", "P2SH,STRICTENC"], +["0", "IF ELSE 1 ENDIF", "P2SH,STRICTENC"], -["1 1", "IF IF 1 ELSE 0 ENDIF ENDIF"], -["1 0", "IF IF 1 ELSE 0 ENDIF ENDIF"], -["1 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], -["0 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], +["1 1", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"], +["1 0", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"], +["1 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"], +["0 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"], -["1 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF"], -["1 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF"], -["1 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], -["0 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], +["1 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"], +["1 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"], +["1 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"], +["0 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"], -["0", "IF 0 ELSE 1 ELSE 0 ENDIF", "Multiple ELSE's are valid and executed inverts on each ELSE encountered"], -["1", "IF 1 ELSE 0 ELSE ENDIF"], -["1", "IF ELSE 0 ELSE 1 ENDIF"], -["1", "IF 1 ELSE 0 ELSE 1 ENDIF ADD 2 EQUAL"], -["'' 1", "IF SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ENDIF 0x14 0x68ca4fec736264c13b859bac43d5173df6871682 EQUAL"], +["0", "IF 0 ELSE 1 ELSE 0 ENDIF", "P2SH,STRICTENC", "Multiple ELSE's are valid and executed inverts on each ELSE encountered"], +["1", "IF 1 ELSE 0 ELSE ENDIF", "P2SH,STRICTENC"], +["1", "IF ELSE 0 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["1", "IF 1 ELSE 0 ELSE 1 ENDIF ADD 2 EQUAL", "P2SH,STRICTENC"], +["'' 1", "IF SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ENDIF 0x14 0x68ca4fec736264c13b859bac43d5173df6871682 EQUAL", "P2SH,STRICTENC"], -["1", "NOTIF 0 ELSE 1 ELSE 0 ENDIF", "Multiple ELSE's are valid and execution inverts on each ELSE encountered"], -["0", "NOTIF 1 ELSE 0 ELSE ENDIF"], -["0", "NOTIF ELSE 0 ELSE 1 ENDIF"], -["0", "NOTIF 1 ELSE 0 ELSE 1 ENDIF ADD 2 EQUAL"], -["'' 0", "NOTIF SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ENDIF 0x14 0x68ca4fec736264c13b859bac43d5173df6871682 EQUAL"], +["1", "NOTIF 0 ELSE 1 ELSE 0 ENDIF", "P2SH,STRICTENC", "Multiple ELSE's are valid and execution inverts on each ELSE encountered"], +["0", "NOTIF 1 ELSE 0 ELSE ENDIF", "P2SH,STRICTENC"], +["0", "NOTIF ELSE 0 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "NOTIF 1 ELSE 0 ELSE 1 ENDIF ADD 2 EQUAL", "P2SH,STRICTENC"], +["'' 0", "NOTIF SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ENDIF 0x14 0x68ca4fec736264c13b859bac43d5173df6871682 EQUAL", "P2SH,STRICTENC"], -["0", "IF 1 IF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 1 IF 1 ELSE RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL", "Nested ELSE ELSE"], -["1", "NOTIF 0 NOTIF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 0 NOTIF 1 ELSE RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL"], +["0", "IF 1 IF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 1 IF 1 ELSE RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL", "P2SH,STRICTENC", "Nested ELSE ELSE"], +["1", "NOTIF 0 NOTIF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 0 NOTIF 1 ELSE RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL", "P2SH,STRICTENC"], -["0", "IF RETURN ENDIF 1", "RETURN only works if executed"], +["0", "IF RETURN ENDIF 1", "P2SH,STRICTENC", "RETURN only works if executed"], -["1 1", "VERIFY"], -["1 0x05 0x01 0x00 0x00 0x00 0x00", "VERIFY", "values >4 bytes can be cast to boolean"], +["1 1", "VERIFY", "P2SH,STRICTENC"], +["1 0x05 0x01 0x00 0x00 0x00 0x00", "VERIFY", "P2SH,STRICTENC", "values >4 bytes can be cast to boolean"], -["10 0 11 TOALTSTACK DROP FROMALTSTACK", "ADD 21 EQUAL"], -["'gavin_was_here' TOALTSTACK 11 FROMALTSTACK", "'gavin_was_here' EQUALVERIFY 11 EQUAL"], +["10 0 11 TOALTSTACK DROP FROMALTSTACK", "ADD 21 EQUAL", "P2SH,STRICTENC"], +["'gavin_was_here' TOALTSTACK 11 FROMALTSTACK", "'gavin_was_here' EQUALVERIFY 11 EQUAL", "P2SH,STRICTENC"], -["0 IFDUP", "DEPTH 1 EQUALVERIFY 0 EQUAL"], -["1 IFDUP", "DEPTH 2 EQUALVERIFY 1 EQUALVERIFY 1 EQUAL"], -["0 DROP", "DEPTH 0 EQUAL"], -["0", "DUP 1 ADD 1 EQUALVERIFY 0 EQUAL"], -["0 1", "NIP"], -["1 0", "OVER DEPTH 3 EQUALVERIFY"], -["22 21 20", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL"], -["22 21 20", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL"], -["22 21 20", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL"], -["22 21 20", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL"], -["22 21 20", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL"], -["22 21 20", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL"], -["22 21 20", "ROT 22 EQUAL"], -["22 21 20", "ROT DROP 20 EQUAL"], -["22 21 20", "ROT DROP DROP 21 EQUAL"], -["22 21 20", "ROT ROT 21 EQUAL"], -["22 21 20", "ROT ROT ROT 20 EQUAL"], -["25 24 23 22 21 20", "2ROT 24 EQUAL"], -["25 24 23 22 21 20", "2ROT DROP 25 EQUAL"], -["25 24 23 22 21 20", "2ROT 2DROP 20 EQUAL"], -["25 24 23 22 21 20", "2ROT 2DROP DROP 21 EQUAL"], -["25 24 23 22 21 20", "2ROT 2DROP 2DROP 22 EQUAL"], -["25 24 23 22 21 20", "2ROT 2DROP 2DROP DROP 23 EQUAL"], -["25 24 23 22 21 20", "2ROT 2ROT 22 EQUAL"], -["25 24 23 22 21 20", "2ROT 2ROT 2ROT 20 EQUAL"], -["1 0", "SWAP 1 EQUALVERIFY 0 EQUAL"], -["0 1", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP"], -["13 14", "2DUP ROT EQUALVERIFY EQUAL"], -["-1 0 1 2", "3DUP DEPTH 7 EQUALVERIFY ADD ADD 3 EQUALVERIFY 2DROP 0 EQUALVERIFY"], -["1 2 3 5", "2OVER ADD ADD 8 EQUALVERIFY ADD ADD 6 EQUAL"], -["1 3 5 7", "2SWAP ADD 4 EQUALVERIFY ADD 12 EQUAL"], -["0", "SIZE 0 EQUAL"], -["1", "SIZE 1 EQUAL"], -["127", "SIZE 1 EQUAL"], -["128", "SIZE 2 EQUAL"], -["32767", "SIZE 2 EQUAL"], -["32768", "SIZE 3 EQUAL"], -["8388607", "SIZE 3 EQUAL"], -["8388608", "SIZE 4 EQUAL"], -["2147483647", "SIZE 4 EQUAL"], -["2147483648", "SIZE 5 EQUAL"], -["549755813887", "SIZE 5 EQUAL"], -["549755813888", "SIZE 6 EQUAL"], -["9223372036854775807", "SIZE 8 EQUAL"], -["-1", "SIZE 1 EQUAL"], -["-127", "SIZE 1 EQUAL"], -["-128", "SIZE 2 EQUAL"], -["-32767", "SIZE 2 EQUAL"], -["-32768", "SIZE 3 EQUAL"], -["-8388607", "SIZE 3 EQUAL"], -["-8388608", "SIZE 4 EQUAL"], -["-2147483647", "SIZE 4 EQUAL"], -["-2147483648", "SIZE 5 EQUAL"], -["-549755813887", "SIZE 5 EQUAL"], -["-549755813888", "SIZE 6 EQUAL"], -["-9223372036854775807", "SIZE 8 EQUAL"], -["'abcdefghijklmnopqrstuvwxyz'", "SIZE 26 EQUAL"], +["0 IFDUP", "DEPTH 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC"], +["1 IFDUP", "DEPTH 2 EQUALVERIFY 1 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC"], +["0 DROP", "DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["0", "DUP 1 ADD 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC"], +["0 1", "NIP", "P2SH,STRICTENC"], +["1 0", "OVER DEPTH 3 EQUALVERIFY", "P2SH,STRICTENC"], +["22 21 20", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC"], +["22 21 20", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC"], +["22 21 20", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC"], +["22 21 20", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"], +["22 21 20", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"], +["22 21 20", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"], +["22 21 20", "ROT 22 EQUAL", "P2SH,STRICTENC"], +["22 21 20", "ROT DROP 20 EQUAL", "P2SH,STRICTENC"], +["22 21 20", "ROT DROP DROP 21 EQUAL", "P2SH,STRICTENC"], +["22 21 20", "ROT ROT 21 EQUAL", "P2SH,STRICTENC"], +["22 21 20", "ROT ROT ROT 20 EQUAL", "P2SH,STRICTENC"], +["25 24 23 22 21 20", "2ROT 24 EQUAL", "P2SH,STRICTENC"], +["25 24 23 22 21 20", "2ROT DROP 25 EQUAL", "P2SH,STRICTENC"], +["25 24 23 22 21 20", "2ROT 2DROP 20 EQUAL", "P2SH,STRICTENC"], +["25 24 23 22 21 20", "2ROT 2DROP DROP 21 EQUAL", "P2SH,STRICTENC"], +["25 24 23 22 21 20", "2ROT 2DROP 2DROP 22 EQUAL", "P2SH,STRICTENC"], +["25 24 23 22 21 20", "2ROT 2DROP 2DROP DROP 23 EQUAL", "P2SH,STRICTENC"], +["25 24 23 22 21 20", "2ROT 2ROT 22 EQUAL", "P2SH,STRICTENC"], +["25 24 23 22 21 20", "2ROT 2ROT 2ROT 20 EQUAL", "P2SH,STRICTENC"], +["1 0", "SWAP 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC"], +["0 1", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP", "P2SH,STRICTENC"], +["13 14", "2DUP ROT EQUALVERIFY EQUAL", "P2SH,STRICTENC"], +["-1 0 1 2", "3DUP DEPTH 7 EQUALVERIFY ADD ADD 3 EQUALVERIFY 2DROP 0 EQUALVERIFY", "P2SH,STRICTENC"], +["1 2 3 5", "2OVER ADD ADD 8 EQUALVERIFY ADD ADD 6 EQUAL", "P2SH,STRICTENC"], +["1 3 5 7", "2SWAP ADD 4 EQUALVERIFY ADD 12 EQUAL", "P2SH,STRICTENC"], +["0", "SIZE 0 EQUAL", "P2SH,STRICTENC"], +["1", "SIZE 1 EQUAL", "P2SH,STRICTENC"], +["127", "SIZE 1 EQUAL", "P2SH,STRICTENC"], +["128", "SIZE 2 EQUAL", "P2SH,STRICTENC"], +["32767", "SIZE 2 EQUAL", "P2SH,STRICTENC"], +["32768", "SIZE 3 EQUAL", "P2SH,STRICTENC"], +["8388607", "SIZE 3 EQUAL", "P2SH,STRICTENC"], +["8388608", "SIZE 4 EQUAL", "P2SH,STRICTENC"], +["2147483647", "SIZE 4 EQUAL", "P2SH,STRICTENC"], +["2147483648", "SIZE 5 EQUAL", "P2SH,STRICTENC"], +["549755813887", "SIZE 5 EQUAL", "P2SH,STRICTENC"], +["549755813888", "SIZE 6 EQUAL", "P2SH,STRICTENC"], +["9223372036854775807", "SIZE 8 EQUAL", "P2SH,STRICTENC"], +["-1", "SIZE 1 EQUAL", "P2SH,STRICTENC"], +["-127", "SIZE 1 EQUAL", "P2SH,STRICTENC"], +["-128", "SIZE 2 EQUAL", "P2SH,STRICTENC"], +["-32767", "SIZE 2 EQUAL", "P2SH,STRICTENC"], +["-32768", "SIZE 3 EQUAL", "P2SH,STRICTENC"], +["-8388607", "SIZE 3 EQUAL", "P2SH,STRICTENC"], +["-8388608", "SIZE 4 EQUAL", "P2SH,STRICTENC"], +["-2147483647", "SIZE 4 EQUAL", "P2SH,STRICTENC"], +["-2147483648", "SIZE 5 EQUAL", "P2SH,STRICTENC"], +["-549755813887", "SIZE 5 EQUAL", "P2SH,STRICTENC"], +["-549755813888", "SIZE 6 EQUAL", "P2SH,STRICTENC"], +["-9223372036854775807", "SIZE 8 EQUAL", "P2SH,STRICTENC"], +["'abcdefghijklmnopqrstuvwxyz'", "SIZE 26 EQUAL", "P2SH,STRICTENC"], -["42", "SIZE 1 EQUALVERIFY 42 EQUAL", "SIZE does not consume argument"], +["42", "SIZE 1 EQUALVERIFY 42 EQUAL", "P2SH,STRICTENC", "SIZE does not consume argument"], -["2 -2 ADD", "0 EQUAL"], -["2147483647 -2147483647 ADD", "0 EQUAL"], -["-1 -1 ADD", "-2 EQUAL"], +["2 -2 ADD", "0 EQUAL", "P2SH,STRICTENC"], +["2147483647 -2147483647 ADD", "0 EQUAL", "P2SH,STRICTENC"], +["-1 -1 ADD", "-2 EQUAL", "P2SH,STRICTENC"], -["0 0","EQUAL"], -["1 1 ADD", "2 EQUAL"], -["1 1ADD", "2 EQUAL"], -["111 1SUB", "110 EQUAL"], -["111 1 ADD 12 SUB", "100 EQUAL"], -["0 ABS", "0 EQUAL"], -["16 ABS", "16 EQUAL"], -["-16 ABS", "-16 NEGATE EQUAL"], -["0 NOT", "NOP"], -["1 NOT", "0 EQUAL"], -["11 NOT", "0 EQUAL"], -["0 0NOTEQUAL", "0 EQUAL"], -["1 0NOTEQUAL", "1 EQUAL"], -["111 0NOTEQUAL", "1 EQUAL"], -["-111 0NOTEQUAL", "1 EQUAL"], -["1 1 BOOLAND", "NOP"], -["1 0 BOOLAND", "NOT"], -["0 1 BOOLAND", "NOT"], -["0 0 BOOLAND", "NOT"], -["16 17 BOOLAND", "NOP"], -["1 1 BOOLOR", "NOP"], -["1 0 BOOLOR", "NOP"], -["0 1 BOOLOR", "NOP"], -["0 0 BOOLOR", "NOT"], -["16 17 BOOLOR", "NOP"], -["11 10 1 ADD", "NUMEQUAL"], -["11 10 1 ADD", "NUMEQUALVERIFY 1"], -["11 10 1 ADD", "NUMNOTEQUAL NOT"], -["111 10 1 ADD", "NUMNOTEQUAL"], -["11 10", "LESSTHAN NOT"], -["4 4", "LESSTHAN NOT"], -["10 11", "LESSTHAN"], -["-11 11", "LESSTHAN"], -["-11 -10", "LESSTHAN"], -["11 10", "GREATERTHAN"], -["4 4", "GREATERTHAN NOT"], -["10 11", "GREATERTHAN NOT"], -["-11 11", "GREATERTHAN NOT"], -["-11 -10", "GREATERTHAN NOT"], -["11 10", "LESSTHANOREQUAL NOT"], -["4 4", "LESSTHANOREQUAL"], -["10 11", "LESSTHANOREQUAL"], -["-11 11", "LESSTHANOREQUAL"], -["-11 -10", "LESSTHANOREQUAL"], -["11 10", "GREATERTHANOREQUAL"], -["4 4", "GREATERTHANOREQUAL"], -["10 11", "GREATERTHANOREQUAL NOT"], -["-11 11", "GREATERTHANOREQUAL NOT"], -["-11 -10", "GREATERTHANOREQUAL NOT"], -["1 0 MIN", "0 NUMEQUAL"], -["0 1 MIN", "0 NUMEQUAL"], -["-1 0 MIN", "-1 NUMEQUAL"], -["0 -2147483647 MIN", "-2147483647 NUMEQUAL"], -["2147483647 0 MAX", "2147483647 NUMEQUAL"], -["0 100 MAX", "100 NUMEQUAL"], -["-100 0 MAX", "0 NUMEQUAL"], -["0 -2147483647 MAX", "0 NUMEQUAL"], -["0 0 1", "WITHIN"], -["1 0 1", "WITHIN NOT"], -["0 -2147483647 2147483647", "WITHIN"], -["-1 -100 100", "WITHIN"], -["11 -100 100", "WITHIN"], -["-2147483647 -100 100", "WITHIN NOT"], -["2147483647 -100 100", "WITHIN NOT"], +["0 0","EQUAL", "P2SH,STRICTENC"], +["1 1 ADD", "2 EQUAL", "P2SH,STRICTENC"], +["1 1ADD", "2 EQUAL", "P2SH,STRICTENC"], +["111 1SUB", "110 EQUAL", "P2SH,STRICTENC"], +["111 1 ADD 12 SUB", "100 EQUAL", "P2SH,STRICTENC"], +["0 ABS", "0 EQUAL", "P2SH,STRICTENC"], +["16 ABS", "16 EQUAL", "P2SH,STRICTENC"], +["-16 ABS", "-16 NEGATE EQUAL", "P2SH,STRICTENC"], +["0 NOT", "NOP", "P2SH,STRICTENC"], +["1 NOT", "0 EQUAL", "P2SH,STRICTENC"], +["11 NOT", "0 EQUAL", "P2SH,STRICTENC"], +["0 0NOTEQUAL", "0 EQUAL", "P2SH,STRICTENC"], +["1 0NOTEQUAL", "1 EQUAL", "P2SH,STRICTENC"], +["111 0NOTEQUAL", "1 EQUAL", "P2SH,STRICTENC"], +["-111 0NOTEQUAL", "1 EQUAL", "P2SH,STRICTENC"], +["1 1 BOOLAND", "NOP", "P2SH,STRICTENC"], +["1 0 BOOLAND", "NOT", "P2SH,STRICTENC"], +["0 1 BOOLAND", "NOT", "P2SH,STRICTENC"], +["0 0 BOOLAND", "NOT", "P2SH,STRICTENC"], +["16 17 BOOLAND", "NOP", "P2SH,STRICTENC"], +["1 1 BOOLOR", "NOP", "P2SH,STRICTENC"], +["1 0 BOOLOR", "NOP", "P2SH,STRICTENC"], +["0 1 BOOLOR", "NOP", "P2SH,STRICTENC"], +["0 0 BOOLOR", "NOT", "P2SH,STRICTENC"], +["16 17 BOOLOR", "NOP", "P2SH,STRICTENC"], +["11 10 1 ADD", "NUMEQUAL", "P2SH,STRICTENC"], +["11 10 1 ADD", "NUMEQUALVERIFY 1", "P2SH,STRICTENC"], +["11 10 1 ADD", "NUMNOTEQUAL NOT", "P2SH,STRICTENC"], +["111 10 1 ADD", "NUMNOTEQUAL", "P2SH,STRICTENC"], +["11 10", "LESSTHAN NOT", "P2SH,STRICTENC"], +["4 4", "LESSTHAN NOT", "P2SH,STRICTENC"], +["10 11", "LESSTHAN", "P2SH,STRICTENC"], +["-11 11", "LESSTHAN", "P2SH,STRICTENC"], +["-11 -10", "LESSTHAN", "P2SH,STRICTENC"], +["11 10", "GREATERTHAN", "P2SH,STRICTENC"], +["4 4", "GREATERTHAN NOT", "P2SH,STRICTENC"], +["10 11", "GREATERTHAN NOT", "P2SH,STRICTENC"], +["-11 11", "GREATERTHAN NOT", "P2SH,STRICTENC"], +["-11 -10", "GREATERTHAN NOT", "P2SH,STRICTENC"], +["11 10", "LESSTHANOREQUAL NOT", "P2SH,STRICTENC"], +["4 4", "LESSTHANOREQUAL", "P2SH,STRICTENC"], +["10 11", "LESSTHANOREQUAL", "P2SH,STRICTENC"], +["-11 11", "LESSTHANOREQUAL", "P2SH,STRICTENC"], +["-11 -10", "LESSTHANOREQUAL", "P2SH,STRICTENC"], +["11 10", "GREATERTHANOREQUAL", "P2SH,STRICTENC"], +["4 4", "GREATERTHANOREQUAL", "P2SH,STRICTENC"], +["10 11", "GREATERTHANOREQUAL NOT", "P2SH,STRICTENC"], +["-11 11", "GREATERTHANOREQUAL NOT", "P2SH,STRICTENC"], +["-11 -10", "GREATERTHANOREQUAL NOT", "P2SH,STRICTENC"], +["1 0 MIN", "0 NUMEQUAL", "P2SH,STRICTENC"], +["0 1 MIN", "0 NUMEQUAL", "P2SH,STRICTENC"], +["-1 0 MIN", "-1 NUMEQUAL", "P2SH,STRICTENC"], +["0 -2147483647 MIN", "-2147483647 NUMEQUAL", "P2SH,STRICTENC"], +["2147483647 0 MAX", "2147483647 NUMEQUAL", "P2SH,STRICTENC"], +["0 100 MAX", "100 NUMEQUAL", "P2SH,STRICTENC"], +["-100 0 MAX", "0 NUMEQUAL", "P2SH,STRICTENC"], +["0 -2147483647 MAX", "0 NUMEQUAL", "P2SH,STRICTENC"], +["0 0 1", "WITHIN", "P2SH,STRICTENC"], +["1 0 1", "WITHIN NOT", "P2SH,STRICTENC"], +["0 -2147483647 2147483647", "WITHIN", "P2SH,STRICTENC"], +["-1 -100 100", "WITHIN", "P2SH,STRICTENC"], +["11 -100 100", "WITHIN", "P2SH,STRICTENC"], +["-2147483647 -100 100", "WITHIN NOT", "P2SH,STRICTENC"], +["2147483647 -100 100", "WITHIN NOT", "P2SH,STRICTENC"], -["2147483647 2147483647 SUB", "0 EQUAL"], -["2147483647 DUP ADD", "4294967294 EQUAL", ">32 bit EQUAL is valid"], -["2147483647 NEGATE DUP ADD", "-4294967294 EQUAL"], +["2147483647 2147483647 SUB", "0 EQUAL", "P2SH,STRICTENC"], +["2147483647 DUP ADD", "4294967294 EQUAL", "P2SH,STRICTENC", ">32 bit EQUAL is valid"], +["2147483647 NEGATE DUP ADD", "-4294967294 EQUAL", "P2SH,STRICTENC"], -["''", "RIPEMD160 0x14 0x9c1185a5c5e9fc54612808977ee8f548b2258d31 EQUAL"], -["'a'", "RIPEMD160 0x14 0x0bdc9d2d256b3ee9daae347be6f4dc835a467ffe EQUAL"], -["'abcdefghijklmnopqrstuvwxyz'", "RIPEMD160 0x14 0xf71c27109c692c1b56bbdceb5b9d2865b3708dbc EQUAL"], -["''", "SHA1 0x14 0xda39a3ee5e6b4b0d3255bfef95601890afd80709 EQUAL"], -["'a'", "SHA1 0x14 0x86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 EQUAL"], -["'abcdefghijklmnopqrstuvwxyz'", "SHA1 0x14 0x32d10c7b8cf96570ca04ce37f2a19d84240d3a89 EQUAL"], -["''", "SHA256 0x20 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 EQUAL"], -["'a'", "SHA256 0x20 0xca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb EQUAL"], -["'abcdefghijklmnopqrstuvwxyz'", "SHA256 0x20 0x71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73 EQUAL"], -["''", "DUP HASH160 SWAP SHA256 RIPEMD160 EQUAL"], -["''", "DUP HASH256 SWAP SHA256 SHA256 EQUAL"], -["''", "NOP HASH160 0x14 0xb472a266d0bd89c13706a4132ccfb16f7c3b9fcb EQUAL"], -["'a'", "HASH160 NOP 0x14 0x994355199e516ff76c4fa4aab39337b9d84cf12b EQUAL"], -["'abcdefghijklmnopqrstuvwxyz'", "HASH160 0x4c 0x14 0xc286a1af0947f58d1ad787385b1c2c4a976f9e71 EQUAL"], -["''", "HASH256 0x20 0x5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456 EQUAL"], -["'a'", "HASH256 0x20 0xbf5d3affb73efd2ec6c36ad3112dd933efed63c4e1cbffcfa88e2759c144f2d8 EQUAL"], -["'abcdefghijklmnopqrstuvwxyz'", "HASH256 0x4c 0x20 0xca139bc10c2f660da42666f72e89a225936fc60f193c161124a672050c434671 EQUAL"], +["''", "RIPEMD160 0x14 0x9c1185a5c5e9fc54612808977ee8f548b2258d31 EQUAL", "P2SH,STRICTENC"], +["'a'", "RIPEMD160 0x14 0x0bdc9d2d256b3ee9daae347be6f4dc835a467ffe EQUAL", "P2SH,STRICTENC"], +["'abcdefghijklmnopqrstuvwxyz'", "RIPEMD160 0x14 0xf71c27109c692c1b56bbdceb5b9d2865b3708dbc EQUAL", "P2SH,STRICTENC"], +["''", "SHA1 0x14 0xda39a3ee5e6b4b0d3255bfef95601890afd80709 EQUAL", "P2SH,STRICTENC"], +["'a'", "SHA1 0x14 0x86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 EQUAL", "P2SH,STRICTENC"], +["'abcdefghijklmnopqrstuvwxyz'", "SHA1 0x14 0x32d10c7b8cf96570ca04ce37f2a19d84240d3a89 EQUAL", "P2SH,STRICTENC"], +["''", "SHA256 0x20 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 EQUAL", "P2SH,STRICTENC"], +["'a'", "SHA256 0x20 0xca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb EQUAL", "P2SH,STRICTENC"], +["'abcdefghijklmnopqrstuvwxyz'", "SHA256 0x20 0x71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73 EQUAL", "P2SH,STRICTENC"], +["''", "DUP HASH160 SWAP SHA256 RIPEMD160 EQUAL", "P2SH,STRICTENC"], +["''", "DUP HASH256 SWAP SHA256 SHA256 EQUAL", "P2SH,STRICTENC"], +["''", "NOP HASH160 0x14 0xb472a266d0bd89c13706a4132ccfb16f7c3b9fcb EQUAL", "P2SH,STRICTENC"], +["'a'", "HASH160 NOP 0x14 0x994355199e516ff76c4fa4aab39337b9d84cf12b EQUAL", "P2SH,STRICTENC"], +["'abcdefghijklmnopqrstuvwxyz'", "HASH160 0x4c 0x14 0xc286a1af0947f58d1ad787385b1c2c4a976f9e71 EQUAL", "P2SH,STRICTENC"], +["''", "HASH256 0x20 0x5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456 EQUAL", "P2SH,STRICTENC"], +["'a'", "HASH256 0x20 0xbf5d3affb73efd2ec6c36ad3112dd933efed63c4e1cbffcfa88e2759c144f2d8 EQUAL", "P2SH,STRICTENC"], +["'abcdefghijklmnopqrstuvwxyz'", "HASH256 0x4c 0x20 0xca139bc10c2f660da42666f72e89a225936fc60f193c161124a672050c434671 EQUAL", "P2SH,STRICTENC"], -["1","NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 1 EQUAL"], -["'NOP_1_to_10' NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' EQUAL"], +["1","NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 1 EQUAL", "P2SH,STRICTENC"], +["'NOP_1_to_10' NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' EQUAL", "P2SH,STRICTENC"], -["0", "IF 0xba ELSE 1 ENDIF", "opcodes above NOP10 invalid if executed"], -["0", "IF 0xbb ELSE 1 ENDIF"], -["0", "IF 0xbc ELSE 1 ENDIF"], -["0", "IF 0xbd ELSE 1 ENDIF"], -["0", "IF 0xbe ELSE 1 ENDIF"], -["0", "IF 0xbf ELSE 1 ENDIF"], -["0", "IF 0xc0 ELSE 1 ENDIF"], -["0", "IF 0xc1 ELSE 1 ENDIF"], -["0", "IF 0xc2 ELSE 1 ENDIF"], -["0", "IF 0xc3 ELSE 1 ENDIF"], -["0", "IF 0xc4 ELSE 1 ENDIF"], -["0", "IF 0xc5 ELSE 1 ENDIF"], -["0", "IF 0xc6 ELSE 1 ENDIF"], -["0", "IF 0xc7 ELSE 1 ENDIF"], -["0", "IF 0xc8 ELSE 1 ENDIF"], -["0", "IF 0xc9 ELSE 1 ENDIF"], -["0", "IF 0xca ELSE 1 ENDIF"], -["0", "IF 0xcb ELSE 1 ENDIF"], -["0", "IF 0xcc ELSE 1 ENDIF"], -["0", "IF 0xcd ELSE 1 ENDIF"], -["0", "IF 0xce ELSE 1 ENDIF"], -["0", "IF 0xcf ELSE 1 ENDIF"], -["0", "IF 0xd0 ELSE 1 ENDIF"], -["0", "IF 0xd1 ELSE 1 ENDIF"], -["0", "IF 0xd2 ELSE 1 ENDIF"], -["0", "IF 0xd3 ELSE 1 ENDIF"], -["0", "IF 0xd4 ELSE 1 ENDIF"], -["0", "IF 0xd5 ELSE 1 ENDIF"], -["0", "IF 0xd6 ELSE 1 ENDIF"], -["0", "IF 0xd7 ELSE 1 ENDIF"], -["0", "IF 0xd8 ELSE 1 ENDIF"], -["0", "IF 0xd9 ELSE 1 ENDIF"], -["0", "IF 0xda ELSE 1 ENDIF"], -["0", "IF 0xdb ELSE 1 ENDIF"], -["0", "IF 0xdc ELSE 1 ENDIF"], -["0", "IF 0xdd ELSE 1 ENDIF"], -["0", "IF 0xde ELSE 1 ENDIF"], -["0", "IF 0xdf ELSE 1 ENDIF"], -["0", "IF 0xe0 ELSE 1 ENDIF"], -["0", "IF 0xe1 ELSE 1 ENDIF"], -["0", "IF 0xe2 ELSE 1 ENDIF"], -["0", "IF 0xe3 ELSE 1 ENDIF"], -["0", "IF 0xe4 ELSE 1 ENDIF"], -["0", "IF 0xe5 ELSE 1 ENDIF"], -["0", "IF 0xe6 ELSE 1 ENDIF"], -["0", "IF 0xe7 ELSE 1 ENDIF"], -["0", "IF 0xe8 ELSE 1 ENDIF"], -["0", "IF 0xe9 ELSE 1 ENDIF"], -["0", "IF 0xea ELSE 1 ENDIF"], -["0", "IF 0xeb ELSE 1 ENDIF"], -["0", "IF 0xec ELSE 1 ENDIF"], -["0", "IF 0xed ELSE 1 ENDIF"], -["0", "IF 0xee ELSE 1 ENDIF"], -["0", "IF 0xef ELSE 1 ENDIF"], -["0", "IF 0xf0 ELSE 1 ENDIF"], -["0", "IF 0xf1 ELSE 1 ENDIF"], -["0", "IF 0xf2 ELSE 1 ENDIF"], -["0", "IF 0xf3 ELSE 1 ENDIF"], -["0", "IF 0xf4 ELSE 1 ENDIF"], -["0", "IF 0xf5 ELSE 1 ENDIF"], -["0", "IF 0xf6 ELSE 1 ENDIF"], -["0", "IF 0xf7 ELSE 1 ENDIF"], -["0", "IF 0xf8 ELSE 1 ENDIF"], -["0", "IF 0xf9 ELSE 1 ENDIF"], -["0", "IF 0xfa ELSE 1 ENDIF"], -["0", "IF 0xfb ELSE 1 ENDIF"], -["0", "IF 0xfc ELSE 1 ENDIF"], -["0", "IF 0xfd ELSE 1 ENDIF"], -["0", "IF 0xfe ELSE 1 ENDIF"], -["0", "IF 0xff ELSE 1 ENDIF"], +["0", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "opcodes above NOP10 invalid if executed"], +["0", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xc0 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xc4 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xc5 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xc6 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xc7 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xc8 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xc9 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xca ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xcb ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xcc ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xcd ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xce ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xcf ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xd0 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xd1 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xd2 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xd3 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xd4 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xd5 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xd6 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xd7 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xd8 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xd9 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xda ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xdb ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xdc ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xdd ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xde ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xdf ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xe0 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xe1 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xe2 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xe3 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xe4 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xe5 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xe6 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xe7 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xe8 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xe9 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xea ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xeb ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xec ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xed ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xee ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xef ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xf0 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xf1 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xf2 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xf3 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xf4 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xf5 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xf6 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xf7 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xf8 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xf9 ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xfa ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xfb ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xfc ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xfd ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xfe ELSE 1 ENDIF", "P2SH,STRICTENC"], +["0", "IF 0xff ELSE 1 ENDIF", "P2SH,STRICTENC"], ["NOP", "'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'", +"P2SH,STRICTENC", "520 byte push"], ["1", "0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", +"P2SH,STRICTENC", "201 opcodes executed. 0x61 is NOP"], ["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", "1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"P2SH,STRICTENC", "1,000 stack size (0x6f is 3DUP)"], ["1 TOALTSTACK 2 TOALTSTACK 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", "1 2 3 4 5 6 7 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"P2SH,STRICTENC", "1,000 stack size (altstack cleared between scriptSig/scriptPubKey)"], ["'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", "'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f 2DUP 0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", +"P2SH,STRICTENC", "Max-size (10,000-byte), max-push(520 bytes), max-opcodes(201), max stack size(1,000 items). 0x6f is 3DUP, 0x61 is NOP"], ["0", "IF 0x5050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050 ENDIF 1", +"P2SH,STRICTENC", ">201 opcodes, but RESERVED (0x50) doesn't count towards opcode limit."], -["NOP","1"], +["NOP","1", "P2SH,STRICTENC"], -["1", "0x01 0x01 EQUAL", "The following is useful for checking implementations of BN_bn2mpi"], -["127", "0x01 0x7F EQUAL"], -["128", "0x02 0x8000 EQUAL", "Leave room for the sign bit"], -["32767", "0x02 0xFF7F EQUAL"], -["32768", "0x03 0x008000 EQUAL"], -["8388607", "0x03 0xFFFF7F EQUAL"], -["8388608", "0x04 0x00008000 EQUAL"], -["2147483647", "0x04 0xFFFFFF7F EQUAL"], -["2147483648", "0x05 0x0000008000 EQUAL"], -["549755813887", "0x05 0xFFFFFFFF7F EQUAL"], -["549755813888", "0x06 0xFFFFFFFF7F EQUAL"], -["9223372036854775807", "0x08 0xFFFFFFFFFFFFFF7F EQUAL"], -["-1", "0x01 0x81 EQUAL", "Numbers are little-endian with the MSB being a sign bit"], -["-127", "0x01 0xFF EQUAL"], -["-128", "0x02 0x8080 EQUAL"], -["-32767", "0x02 0xFFFF EQUAL"], -["-32768", "0x03 0x008080 EQUAL"], -["-8388607", "0x03 0xFFFFFF EQUAL"], -["-8388608", "0x04 0x00008080 EQUAL"], -["-2147483647", "0x04 0xFFFFFFFF EQUAL"], -["-2147483648", "0x05 0x0000008080 EQUAL"], -["-4294967295", "0x05 0xFFFFFFFF80 EQUAL"], -["-549755813887", "0x05 0xFFFFFFFFFF EQUAL"], -["-549755813888", "0x06 0x000000008080 EQUAL"], -["-9223372036854775807", "0x08 0xFFFFFFFFFFFFFFFF EQUAL"], +["1", "0x01 0x01 EQUAL", "P2SH,STRICTENC", "The following is useful for checking implementations of BN_bn2mpi"], +["127", "0x01 0x7F EQUAL", "P2SH,STRICTENC"], +["128", "0x02 0x8000 EQUAL", "P2SH,STRICTENC", "Leave room for the sign bit"], +["32767", "0x02 0xFF7F EQUAL", "P2SH,STRICTENC"], +["32768", "0x03 0x008000 EQUAL", "P2SH,STRICTENC"], +["8388607", "0x03 0xFFFF7F EQUAL", "P2SH,STRICTENC"], +["8388608", "0x04 0x00008000 EQUAL", "P2SH,STRICTENC"], +["2147483647", "0x04 0xFFFFFF7F EQUAL", "P2SH,STRICTENC"], +["2147483648", "0x05 0x0000008000 EQUAL", "P2SH,STRICTENC"], +["549755813887", "0x05 0xFFFFFFFF7F EQUAL", "P2SH,STRICTENC"], +["549755813888", "0x06 0xFFFFFFFF7F EQUAL", "P2SH,STRICTENC"], +["9223372036854775807", "0x08 0xFFFFFFFFFFFFFF7F EQUAL", "P2SH,STRICTENC"], +["-1", "0x01 0x81 EQUAL", "P2SH,STRICTENC", "Numbers are little-endian with the MSB being a sign bit"], +["-127", "0x01 0xFF EQUAL", "P2SH,STRICTENC"], +["-128", "0x02 0x8080 EQUAL", "P2SH,STRICTENC"], +["-32767", "0x02 0xFFFF EQUAL", "P2SH,STRICTENC"], +["-32768", "0x03 0x008080 EQUAL", "P2SH,STRICTENC"], +["-8388607", "0x03 0xFFFFFF EQUAL", "P2SH,STRICTENC"], +["-8388608", "0x04 0x00008080 EQUAL", "P2SH,STRICTENC"], +["-2147483647", "0x04 0xFFFFFFFF EQUAL", "P2SH,STRICTENC"], +["-2147483648", "0x05 0x0000008080 EQUAL", "P2SH,STRICTENC"], +["-4294967295", "0x05 0xFFFFFFFF80 EQUAL", "P2SH,STRICTENC"], +["-549755813887", "0x05 0xFFFFFFFFFF EQUAL", "P2SH,STRICTENC"], +["-549755813888", "0x06 0x000000008080 EQUAL", "P2SH,STRICTENC"], +["-9223372036854775807", "0x08 0xFFFFFFFFFFFFFFFF EQUAL", "P2SH,STRICTENC"], -["2147483647", "1ADD 2147483648 EQUAL", "We can do math on 4-byte integers, and compare 5-byte ones"], -["2147483647", "1ADD 1"], -["-2147483647", "1ADD 1"], +["2147483647", "1ADD 2147483648 EQUAL", "P2SH,STRICTENC", "We can do math on 4-byte integers, and compare 5-byte ones"], +["2147483647", "1ADD 1", "P2SH,STRICTENC"], +["-2147483647", "1ADD 1", "P2SH,STRICTENC"], -["1", "0x02 0x0100 EQUAL NOT", "Not the same byte array..."], -["1", "0x02 0x0100 NUMEQUAL", "... but they are numerically equal"], -["11", "0x4c 0x03 0x0b0000 NUMEQUAL"], -["0", "0x01 0x80 EQUAL NOT"], -["0", "0x01 0x80 NUMEQUAL", "Zero numerically equals negative zero"], -["0", "0x02 0x0080 NUMEQUAL"], -["0x03 0x000080", "0x04 0x00000080 NUMEQUAL"], -["0x03 0x100080", "0x04 0x10000080 NUMEQUAL"], -["0x03 0x100000", "0x04 0x10000000 NUMEQUAL"], +["1", "0x02 0x0100 EQUAL NOT", "P2SH,STRICTENC", "Not the same byte array..."], +["1", "0x02 0x0100 NUMEQUAL", "P2SH,STRICTENC", "... but they are numerically equal"], +["11", "0x4c 0x03 0x0b0000 NUMEQUAL", "P2SH,STRICTENC"], +["0", "0x01 0x80 EQUAL NOT", "P2SH,STRICTENC"], +["0", "0x01 0x80 NUMEQUAL", "P2SH,STRICTENC", "Zero numerically equals negative zero"], +["0", "0x02 0x0080 NUMEQUAL", "P2SH,STRICTENC"], +["0x03 0x000080", "0x04 0x00000080 NUMEQUAL", "P2SH,STRICTENC"], +["0x03 0x100080", "0x04 0x10000080 NUMEQUAL", "P2SH,STRICTENC"], +["0x03 0x100000", "0x04 0x10000000 NUMEQUAL", "P2SH,STRICTENC"], -["NOP", "NOP 1", "The following tests check the if(stack.size() < N) tests in each opcode"], -["1", "IF 1 ENDIF", "They are here to catch copy-and-paste errors"], -["0", "NOTIF 1 ENDIF", "Most of them are duplicated elsewhere,"], -["1", "VERIFY 1", "but, hey, more is always better, right?"], +["NOP", "NOP 1", "P2SH,STRICTENC", "The following tests check the if(stack.size() < N) tests in each opcode"], +["1", "IF 1 ENDIF", "P2SH,STRICTENC", "They are here to catch copy-and-paste errors"], +["0", "NOTIF 1 ENDIF", "P2SH,STRICTENC", "Most of them are duplicated elsewhere,"], +["1", "VERIFY 1", "P2SH,STRICTENC", "but, hey, more is always better, right?"], -["0", "TOALTSTACK 1"], -["1", "TOALTSTACK FROMALTSTACK"], -["0 0", "2DROP 1"], -["0 1", "2DUP"], -["0 0 1", "3DUP"], -["0 1 0 0", "2OVER"], -["0 1 0 0 0 0", "2ROT"], -["0 1 0 0", "2SWAP"], -["1", "IFDUP"], -["NOP", "DEPTH 1"], -["0", "DROP 1"], -["1", "DUP"], -["0 1", "NIP"], -["1 0", "OVER"], -["1 0 0 0 3", "PICK"], -["1 0", "PICK"], -["1 0 0 0 3", "ROLL"], -["1 0", "ROLL"], -["1 0 0", "ROT"], -["1 0", "SWAP"], -["0 1", "TUCK"], +["0", "TOALTSTACK 1", "P2SH,STRICTENC"], +["1", "TOALTSTACK FROMALTSTACK", "P2SH,STRICTENC"], +["0 0", "2DROP 1", "P2SH,STRICTENC"], +["0 1", "2DUP", "P2SH,STRICTENC"], +["0 0 1", "3DUP", "P2SH,STRICTENC"], +["0 1 0 0", "2OVER", "P2SH,STRICTENC"], +["0 1 0 0 0 0", "2ROT", "P2SH,STRICTENC"], +["0 1 0 0", "2SWAP", "P2SH,STRICTENC"], +["1", "IFDUP", "P2SH,STRICTENC"], +["NOP", "DEPTH 1", "P2SH,STRICTENC"], +["0", "DROP 1", "P2SH,STRICTENC"], +["1", "DUP", "P2SH,STRICTENC"], +["0 1", "NIP", "P2SH,STRICTENC"], +["1 0", "OVER", "P2SH,STRICTENC"], +["1 0 0 0 3", "PICK", "P2SH,STRICTENC"], +["1 0", "PICK", "P2SH,STRICTENC"], +["1 0 0 0 3", "ROLL", "P2SH,STRICTENC"], +["1 0", "ROLL", "P2SH,STRICTENC"], +["1 0 0", "ROT", "P2SH,STRICTENC"], +["1 0", "SWAP", "P2SH,STRICTENC"], +["0 1", "TUCK", "P2SH,STRICTENC"], -["1", "SIZE"], +["1", "SIZE", "P2SH,STRICTENC"], -["0 0", "EQUAL"], -["0 0", "EQUALVERIFY 1"], +["0 0", "EQUAL", "P2SH,STRICTENC"], +["0 0", "EQUALVERIFY 1", "P2SH,STRICTENC"], -["0", "1ADD"], -["2", "1SUB"], -["-1", "NEGATE"], -["-1", "ABS"], -["0", "NOT"], -["-1", "0NOTEQUAL"], +["0", "1ADD", "P2SH,STRICTENC"], +["2", "1SUB", "P2SH,STRICTENC"], +["-1", "NEGATE", "P2SH,STRICTENC"], +["-1", "ABS", "P2SH,STRICTENC"], +["0", "NOT", "P2SH,STRICTENC"], +["-1", "0NOTEQUAL", "P2SH,STRICTENC"], -["1 0", "ADD"], -["1 0", "SUB"], -["-1 -1", "BOOLAND"], -["-1 0", "BOOLOR"], -["0 0", "NUMEQUAL"], -["0 0", "NUMEQUALVERIFY 1"], -["-1 0", "NUMNOTEQUAL"], -["-1 0", "LESSTHAN"], -["1 0", "GREATERTHAN"], -["0 0", "LESSTHANOREQUAL"], -["0 0", "GREATERTHANOREQUAL"], -["-1 0", "MIN"], -["1 0", "MAX"], -["-1 -1 0", "WITHIN"], +["1 0", "ADD", "P2SH,STRICTENC"], +["1 0", "SUB", "P2SH,STRICTENC"], +["-1 -1", "BOOLAND", "P2SH,STRICTENC"], +["-1 0", "BOOLOR", "P2SH,STRICTENC"], +["0 0", "NUMEQUAL", "P2SH,STRICTENC"], +["0 0", "NUMEQUALVERIFY 1", "P2SH,STRICTENC"], +["-1 0", "NUMNOTEQUAL", "P2SH,STRICTENC"], +["-1 0", "LESSTHAN", "P2SH,STRICTENC"], +["1 0", "GREATERTHAN", "P2SH,STRICTENC"], +["0 0", "LESSTHANOREQUAL", "P2SH,STRICTENC"], +["0 0", "GREATERTHANOREQUAL", "P2SH,STRICTENC"], +["-1 0", "MIN", "P2SH,STRICTENC"], +["1 0", "MAX", "P2SH,STRICTENC"], +["-1 -1 0", "WITHIN", "P2SH,STRICTENC"], -["0", "RIPEMD160"], -["0", "SHA1"], -["0", "SHA256"], -["0", "HASH160"], -["0", "HASH256"], -["NOP", "CODESEPARATOR 1"], +["0", "RIPEMD160", "P2SH,STRICTENC"], +["0", "SHA1", "P2SH,STRICTENC"], +["0", "SHA256", "P2SH,STRICTENC"], +["0", "HASH160", "P2SH,STRICTENC"], +["0", "HASH256", "P2SH,STRICTENC"], +["NOP", "CODESEPARATOR 1", "P2SH,STRICTENC"], -["NOP", "NOP1 1"], -["NOP", "NOP2 1"], -["NOP", "NOP3 1"], -["NOP", "NOP4 1"], -["NOP", "NOP5 1"], -["NOP", "NOP6 1"], -["NOP", "NOP7 1"], -["NOP", "NOP8 1"], -["NOP", "NOP9 1"], -["NOP", "NOP10 1"], +["NOP", "NOP1 1", "P2SH,STRICTENC"], +["NOP", "NOP2 1", "P2SH,STRICTENC"], +["NOP", "NOP3 1", "P2SH,STRICTENC"], +["NOP", "NOP4 1", "P2SH,STRICTENC"], +["NOP", "NOP5 1", "P2SH,STRICTENC"], +["NOP", "NOP6 1", "P2SH,STRICTENC"], +["NOP", "NOP7 1", "P2SH,STRICTENC"], +["NOP", "NOP8 1", "P2SH,STRICTENC"], +["NOP", "NOP9 1", "P2SH,STRICTENC"], +["NOP", "NOP10 1", "P2SH,STRICTENC"], -["", "0 0 0 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "CHECKMULTISIG is allowed to have zero keys and/or sigs"], -["", "0 0 0 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], -["", "0 0 0 1 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "Zero sigs means no sigs are checked"], -["", "0 0 0 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 0 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "CHECKMULTISIG is allowed to have zero keys and/or sigs"], +["", "0 0 0 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 0 1 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "Zero sigs means no sigs are checked"], +["", "0 0 0 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 0 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "CHECKMULTISIG is allowed to have zero keys and/or sigs"], -["", "0 0 0 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], -["", "0 0 0 1 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "Zero sigs means no sigs are checked"], -["", "0 0 0 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 0 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "CHECKMULTISIG is allowed to have zero keys and/or sigs"], +["", "0 0 0 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 0 1 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "Zero sigs means no sigs are checked"], +["", "0 0 0 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], -["", "0 0 'a' 'b' 2 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "Test from up to 20 pubkeys, all not checked"], -["", "0 0 'a' 'b' 'c' 3 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 4 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 5 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 6 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 7 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 8 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 9 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 10 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 11 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 12 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 13 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 14 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 15 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 16 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 17 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 18 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 19 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 2 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 3 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 4 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 5 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 6 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 7 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 8 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 9 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 10 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 11 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 12 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 13 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 14 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 15 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 16 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 17 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 18 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 19 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], -["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 2 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "Test from up to 20 pubkeys, all not checked"], +["", "0 0 'a' 'b' 'c' 3 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 4 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 5 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 6 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 7 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 8 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 9 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 10 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 11 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 12 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 13 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 14 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 15 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 16 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 17 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 18 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 19 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 2 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 3 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 4 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 5 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 6 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 7 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 8 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 9 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 10 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 11 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 12 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 13 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 14 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 15 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 16 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 17 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 18 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 19 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"], ["", "0 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG", +"P2SH,STRICTENC", "nOpCount is incremented by the number of keys evaluated in addition to the usual one op per op. In this case we have zero keys, so we can execute 201 CHECKMULTISIGS"], ["1", -"0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY"], +"0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY", +"P2SH,STRICTENC"], ["", "NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG", +"P2SH,STRICTENC", "Even though there are no signatures being checked nOpCount is incremented by the number of keys."], ["1", -"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY"], +"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY", +"P2SH,STRICTENC"], -["0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "Very basic P2SH"], -["0x4c 0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL"], +["0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "Very basic P2SH"], +["0x4c 0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC"], ["0x40 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242", "0x4d 0x4000 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 EQUAL", +"P2SH,STRICTENC", "Basic PUSH signedness check"], ["0x4c 0x40 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242", "0x4d 0x4000 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 EQUAL", +"P2SH,STRICTENC", "Basic PUSHDATA1 signedness check"], -["0x00", "SIZE 0 EQUAL", "Basic OP_0 execution"] +["0x00", "SIZE 0 EQUAL", "P2SH,STRICTENC", "Basic OP_0 execution"] ] diff --git a/internal_test.go b/internal_test.go index 8193dc59..b1173ade 100644 --- a/internal_test.go +++ b/internal_test.go @@ -3808,18 +3808,12 @@ func TestBitcoindInvalidTests(t *testing.T) { } tx := btcwire.NewMsgTx() for x, test := range tests { - if len(test) < 2 && len(test) > 3 { + name, err := testName(test) + if err != nil { t.Errorf("TestBitcoindInvalidTests: invalid test #%d\n", x) continue } - name := "" - if len(test) == 3 { - name = fmt.Sprintf("test (%s)", test[2]) - } else { - name = fmt.Sprintf("test ([%s, %s])", test[0], test[1]) - } - scriptSig, err := ParseShortForm(test[0]) if err != nil { t.Errorf("%s: can't parse scriptSig; %v", name, err) @@ -3832,7 +3826,13 @@ func TestBitcoindInvalidTests(t *testing.T) { continue } - s, err := NewScript(scriptSig, scriptPubKey, 0, tx, ScriptBip16) + flags, err := parseScriptFlags(test[2]) + if err != nil { + t.Errorf("%s: %v", name, err) + continue + } + + s, err := NewScript(scriptSig, scriptPubKey, 0, tx, flags) if err == nil { if err := s.Execute(); err == nil { t.Errorf("%s test succeeded when it "+ @@ -3853,23 +3853,18 @@ func TestBitcoindValidTests(t *testing.T) { var tests [][]string err = json.Unmarshal(file, &tests) if err != nil { - t.Errorf("TestBitcoindInvalidTests couldn't Unmarshal: %v\n", + t.Errorf("TestBitcoindValidTests couldn't Unmarshal: %v\n", err) return } tx := btcwire.NewMsgTx() for x, test := range tests { - if len(test) < 2 && len(test) > 3 { - t.Errorf("TestBitcoindInvalidTests: invalid test #%d\n", + name, err := testName(test) + if err != nil { + t.Errorf("TestBitcoindValidTests: invalid test #%d\n", x) continue } - name := "" - if len(test) == 3 { - name = fmt.Sprintf("test (%s)", test[2]) - } else { - name = fmt.Sprintf("test ([%s, %s])", test[0], test[1]) - } scriptSig, err := ParseShortForm(test[0]) if err != nil { @@ -3883,7 +3878,13 @@ func TestBitcoindValidTests(t *testing.T) { continue } - s, err := NewScript(scriptSig, scriptPubKey, 0, tx, ScriptBip16) + flags, err := parseScriptFlags(test[2]) + if err != nil { + t.Errorf("%s: %v", name, err) + continue + } + + s, err := NewScript(scriptSig, scriptPubKey, 0, tx, flags) if err != nil { t.Errorf("%s failed to create script: %v", name, err) continue @@ -3952,15 +3953,10 @@ testloop: continue } - var flags ScriptFlags - vFlags := strings.Split(verifyFlags, ",") - for _, flag := range vFlags { - switch flag { - case "P2SH": - flags |= ScriptBip16 - case "NULLDUMMY": - flags |= ScriptStrictMultiSig - } + flags, err := parseScriptFlags(verifyFlags) + if err != nil { + t.Errorf("bad test %d: %v", i, err) + continue } prevOuts := make(map[btcwire.OutPoint][]byte) @@ -4098,15 +4094,10 @@ testloop: continue } - var flags ScriptFlags - vFlags := strings.Split(verifyFlags, ",") - for _, flag := range vFlags { - switch flag { - case "P2SH": - flags |= ScriptBip16 - case "NULLDUMMY": - flags |= ScriptStrictMultiSig - } + flags, err := parseScriptFlags(verifyFlags) + if err != nil { + t.Errorf("bad test %d: %v", i, err) + continue } prevOuts := make(map[btcwire.OutPoint][]byte) @@ -4190,3 +4181,40 @@ testloop: i, test) } } + +func parseScriptFlags(flagStr string) (ScriptFlags, error) { + var flags ScriptFlags + + sFlags := strings.Split(flagStr, ",") + for _, flag := range sFlags { + switch flag { + case "NONE": + // Nothing. + case "NULLDUMMY": + flags |= ScriptStrictMultiSig + case "P2SH": + flags |= ScriptBip16 + case "STRICTENC": + // This is always set. + default: + return flags, fmt.Errorf("invalid flag: %s", flag) + } + } + return flags, nil +} + +func testName(test []string) (string, error) { + var name string + + if len(test) < 3 || len(test) > 4 { + return name, fmt.Errorf("invalid test length %d", len(test)) + } + + if len(test) == 4 { + name = fmt.Sprintf("test (%s)", test[3]) + } else { + name = fmt.Sprintf("test ([%s, %s, %s])", test[0], test[1], + test[2]) + } + return name, nil +} From bca3d5ba7beeaf77c6b2e4d013fb08ab371972c0 Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Thu, 11 Dec 2014 10:31:17 -0500 Subject: [PATCH 157/174] Switch to new subrepo import paths. --- opcode.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/opcode.go b/opcode.go index 99071802..053d268e 100644 --- a/opcode.go +++ b/opcode.go @@ -13,7 +13,8 @@ import ( "hash" "math/big" - "code.google.com/p/go.crypto/ripemd160" + "golang.org/x/crypto/ripemd160" + "github.com/conformal/btcec" "github.com/conformal/btcwire" "github.com/conformal/fastsha256" From 45e7fe103f6bd93d31ced7d2fecb2068b6245dd9 Mon Sep 17 00:00:00 2001 From: David Hill Date: Fri, 19 Dec 2014 15:20:48 -0500 Subject: [PATCH 158/174] Sync TX tests with Bitcoin Core. --- data/tx_invalid.json | 10 ++++ data/tx_valid.json | 8 +++ test_coverage.txt | 122 +++++++++++++++++++++---------------------- 3 files changed, 79 insertions(+), 61 deletions(-) diff --git a/data/tx_invalid.json b/data/tx_invalid.json index 89533da0..d5f7d7dc 100644 --- a/data/tx_invalid.json +++ b/data/tx_invalid.json @@ -97,5 +97,15 @@ [[["ad503f72c18df5801ee64d76090afe4c607fb2b822e9b7b63c5826c50e22fc3b", 0, "0x21 0x027c3a97665bf283a102a587a62a30a0c102d4d3b141015e2cae6f64e2543113e5 CHECKSIG NOT"]], "01000000013bfc220ec526583cb6b7e922b8b27f604cfe0a09764de61e80f58dc1723f50ad0000000000ffffffff0101000000000000002321027c3a97665bf283a102a587a62a30a0c102d4d3b141015e2cae6f64e2543113e5ac00000000", "P2SH"], +["Inverted versions of tx_valid CODESEPARATOR IF block tests"], + +["CODESEPARATOR in an unexecuted IF block does not change what is hashed"], +[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]], +"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a48304502207a6974a77c591fa13dff60cabbb85a0de9e025c09c65a4b2285e47ce8e22f761022100f0efaac9ff8ac36b10721e0aae1fb975c90500b50c56e8a0cc52b0403f0425dd0151ffffffff010000000000000000016a00000000", "P2SH"], + +["As above, with the IF block executed"], +[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]], +"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a483045022100fa4a74ba9fd59c59f46c3960cf90cbe0d2b743c471d24a3d5d6db6002af5eebb02204d70ec490fd0f7055a7c45f86514336e3a7f03503dacecabb247fc23f15c83510100ffffffff010000000000000000016a00000000", "P2SH"], + ["Make diffs cleaner by leaving a comment here without comma at the end"] ] diff --git a/data/tx_valid.json b/data/tx_valid.json index aa8e5ca6..026771d4 100644 --- a/data/tx_valid.json +++ b/data/tx_valid.json @@ -149,6 +149,14 @@ [[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIGVERIFY CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIGVERIFY CODESEPARATOR 1"]], "010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a900000000924830450221009c0a27f886a1d8cb87f6f595fbc3163d28f7a81ec3c4b252ee7f3ac77fd13ffa02203caa8dfa09713c8c4d7ef575c75ed97812072405d932bd11e6a1593a98b679370148304502201e3861ef39a526406bad1e20ecad06be7375ad40ddb582c9be42d26c3a0d7b240221009d0a3985e96522e59635d19cc4448547477396ce0ef17a58e7d74c3ef464292301ffffffff010000000000000000016a00000000", "P2SH"], +["CODESEPARATOR in an unexecuted IF block does not change what is hashed"], +[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]], +"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a48304502207a6974a77c591fa13dff60cabbb85a0de9e025c09c65a4b2285e47ce8e22f761022100f0efaac9ff8ac36b10721e0aae1fb975c90500b50c56e8a0cc52b0403f0425dd0100ffffffff010000000000000000016a00000000", "P2SH"], + +["As above, with the IF block executed"], +[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]], +"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a483045022100fa4a74ba9fd59c59f46c3960cf90cbe0d2b743c471d24a3d5d6db6002af5eebb02204d70ec490fd0f7055a7c45f86514336e3a7f03503dacecabb247fc23f15c83510151ffffffff010000000000000000016a00000000", "P2SH"], + ["CHECKSIG is legal in scriptSigs"], [[["ccf7f4053a02e653c36ac75c891b7496d0dc5ce5214f6c913d9cf8f1329ebee0", 0, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]], "0100000001e0be9e32f1f89c3d916c4f21e55cdcd096741b895cc76ac353e6023a05f4f7cc00000000d86149304602210086e5f736a2c3622ebb62bd9d93d8e5d76508b98be922b97160edc3dcca6d8c47022100b23c312ac232a4473f19d2aeb95ab7bdf2b65518911a0d72d50e38b5dd31dc820121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac4730440220508fa761865c8abd81244a168392876ee1d94e8ed83897066b5e2df2400dad24022043f5ee7538e87e9c6aef7ef55133d3e51da7cc522830a9c4d736977a76ef755c0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"], diff --git a/test_coverage.txt b/test_coverage.txt index dcc570f4..61d9a98b 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -36,52 +36,51 @@ github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) github.com/conformal/btcscript/script.go PushedData 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) -github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) -github.com/conformal/btcscript/script.go Script.CheckErrorCondition 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) github.com/conformal/btcscript/script.go SignatureScript 100.00% (9/9) +github.com/conformal/btcscript/script.go Script.CheckErrorCondition 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) +github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) -github.com/conformal/btcscript/script.go Script.Execute 100.00% (8/8) -github.com/conformal/btcscript/script.go CalcMultiSigStats 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) +github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) github.com/conformal/btcscript/script.go MultiSigScript 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) -github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/script.go CalcMultiSigStats 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) +github.com/conformal/btcscript/script.go Script.Execute 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) github.com/conformal/btcscript/script.go HasCanonicalPushes 100.00% (7/7) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddUint64 100.00% (7/7) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddInt64 100.00% (7/7) github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodePick 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodePick 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) @@ -93,90 +92,91 @@ github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4) github.com/conformal/btcscript/opcode.go parsedOpcode.alwaysIllegal 100.00% (4/4) -github.com/conformal/btcscript/script.go @1329:17 100.00% (4/4) +github.com/conformal/btcscript/script.go @1322:17 100.00% (4/4) github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) -github.com/conformal/btcscript/script.go setStack 100.00% (3/3) -github.com/conformal/btcscript/script.go isSmallInt 100.00% (3/3) +github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) -github.com/conformal/btcscript/script.go asSmallInt 100.00% (3/3) github.com/conformal/btcscript/script.go ScriptClass.String 100.00% (3/3) -github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/script.go isSmallInt 100.00% (3/3) +github.com/conformal/btcscript/script.go setStack 100.00% (3/3) +github.com/conformal/btcscript/script.go asSmallInt 100.00% (3/3) +github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) -github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddOp 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Reset 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) +github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) +github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) +github.com/conformal/btcscript/script.go KeyClosure.GetKey 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) github.com/conformal/btcscript/script.go payToPubKeyHashScript 100.00% (1/1) github.com/conformal/btcscript/script.go payToScriptHashScript 100.00% (1/1) github.com/conformal/btcscript/script.go payToPubKeyScript 100.00% (1/1) github.com/conformal/btcscript/opcode.go init 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) -github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) -github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) -github.com/conformal/btcscript/script.go signTxOutput 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) -github.com/conformal/btcscript/script.go KeyClosure.GetKey 100.00% (1/1) -github.com/conformal/btcscript/script.go ScriptClosure.GetScript 100.00% (1/1) -github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/log.go init 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) -github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) github.com/conformal/btcscript/scriptbuilder.go NewScriptBuilder 100.00% (1/1) github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) +github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) +github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) +github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) +github.com/conformal/btcscript/script.go ScriptClosure.GetScript 100.00% (1/1) +github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) +github.com/conformal/btcscript/log.go init 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) +github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.48% (65/66) github.com/conformal/btcscript/script.go mergeScripts 95.00% (19/20) github.com/conformal/btcscript/script.go canonicalPush 92.86% (13/14) github.com/conformal/btcscript/script.go signMultiSig 92.86% (13/14) github.com/conformal/btcscript/script.go mergeMultiSig 88.10% (37/42) -github.com/conformal/btcscript/script.go signTxOutputCustomReader 87.50% (7/8) +github.com/conformal/btcscript/script.go signTxOutput 87.50% (7/8) github.com/conformal/btcscript/script.go unparseScript 85.71% (6/7) github.com/conformal/btcscript/script.go expectedInputs 85.71% (6/7) github.com/conformal/btcscript/script.go SignTxOutput 80.00% (12/15) github.com/conformal/btcscript/script.go p2pkSignatureScript 75.00% (3/4) github.com/conformal/btcscript/script.go sign 69.23% (18/26) github.com/conformal/btcscript/script.go @586:34 0.00% (0/6) +github.com/conformal/btcscript/stack.go Stack.String 0.00% (0/4) github.com/conformal/btcscript/script.go @574:34 0.00% (0/4) github.com/conformal/btcscript/script.go @619:34 0.00% (0/3) -github.com/conformal/btcscript/opcode.go @1803:33 0.00% (0/1) github.com/conformal/btcscript/opcode.go opcodeDisabled 0.00% (0/1) +github.com/conformal/btcscript/opcode.go @1804:33 0.00% (0/1) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 96.83% (1222/1262) +github.com/conformal/btcscript -------------------------- 96.52% (1221/1265) From 2f902a5880b62e97cc0f34f2ade49c3692ba3d28 Mon Sep 17 00:00:00 2001 From: Guilherme Salgado Date: Fri, 31 Oct 2014 10:14:41 -0200 Subject: [PATCH 159/174] Rename signTxOutput to RawTxInSignature --- script.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/script.go b/script.go index 4e0e165c..3ec0f5c9 100644 --- a/script.go +++ b/script.go @@ -1098,7 +1098,7 @@ func MultiSigScript(pubkeys []*btcutil.AddressPubKey, nrequired int) ([]byte, er // compress. This format must match the same format used to generate // the payment address, or the script validation will fail. func SignatureScript(tx *btcwire.MsgTx, idx int, subscript []byte, hashType SigHashType, privKey *btcec.PrivateKey, compress bool) ([]byte, error) { - sig, err := signTxOutput(tx, idx, subscript, hashType, privKey) + sig, err := RawTxInSignature(tx, idx, subscript, hashType, privKey) if err != nil { return nil, err } @@ -1114,7 +1114,9 @@ func SignatureScript(tx *btcwire.MsgTx, idx int, subscript []byte, hashType SigH return NewScriptBuilder().AddData(sig).AddData(pkData).Script(), nil } -func signTxOutput(tx *btcwire.MsgTx, idx int, subScript []byte, +// RawTxInSignature returns the serialized ECDSA signature for the input +// idx of the given transaction, with hashType appended to it. +func RawTxInSignature(tx *btcwire.MsgTx, idx int, subScript []byte, hashType SigHashType, key *btcec.PrivateKey) ([]byte, error) { parsedScript, err := parseScript(subScript) if err != nil { @@ -1130,7 +1132,7 @@ func signTxOutput(tx *btcwire.MsgTx, idx int, subScript []byte, } func p2pkSignatureScript(tx *btcwire.MsgTx, idx int, subScript []byte, hashType SigHashType, privKey *btcec.PrivateKey) ([]byte, error) { - sig, err := signTxOutput(tx, idx, subScript, hashType, privKey) + sig, err := RawTxInSignature(tx, idx, subScript, hashType, privKey) if err != nil { return nil, err } @@ -1154,7 +1156,7 @@ func signMultiSig(tx *btcwire.MsgTx, idx int, subScript []byte, hashType SigHash if err != nil { continue } - sig, err := signTxOutput(tx, idx, subScript, hashType, key) + sig, err := RawTxInSignature(tx, idx, subScript, hashType, key) if err != nil { continue } From 8e1973d865c981f6dee0fad06af86cdcd3f83fa8 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 19 Dec 2014 23:44:27 -0600 Subject: [PATCH 160/174] Correct a couple of typos spotted while reviewing. --- internal_test.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/internal_test.go b/internal_test.go index b1173ade..8d80dcec 100644 --- a/internal_test.go +++ b/internal_test.go @@ -3913,8 +3913,10 @@ func TestBitcoindTxValidTests(t *testing.T) { return } - // for ma is eaitehr a ["this is a comment "] - // or [[[previous hash, previous index, previous scripbPubKey]...,] + // form is either: + // ["this is a comment "] + // or: + // [[[previous hash, previous index, previous scriptPubKey]...,] // serializedTransaction, verifyFlags] testloop: for i, test := range tests { @@ -3924,9 +3926,8 @@ testloop: } if len(test) != 3 { - t.Errorf("bad test (bad lenggh) %d: %v", i, test) + t.Errorf("bad test (bad length) %d: %v", i, test) continue - } serializedhex, ok := test[1].(string) if !ok { @@ -4054,8 +4055,10 @@ func TestBitcoindTxInvalidTests(t *testing.T) { return } - // for ma is eaitehr a ["this is a comment "] - // or [[[previous hash, previous index, previous scripbPubKey]...,] + // form is either: + // ["this is a comment "] + // or: + // [[[previous hash, previous index, previous scriptPubKey]...,] // serializedTransaction, verifyFlags] testloop: for i, test := range tests { From c4f1ed69d28794c4b0e5034ea402a0d9a148a509 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 15 Jan 2015 10:42:26 -0600 Subject: [PATCH 161/174] Update btcutil import paths to new location. --- address.go | 2 +- address_test.go | 2 +- example_test.go | 2 +- internal_test.go | 2 +- script.go | 2 +- script_test.go | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/address.go b/address.go index 979abf0e..e9644482 100644 --- a/address.go +++ b/address.go @@ -5,8 +5,8 @@ package btcscript import ( + "github.com/btcsuite/btcutil" "github.com/conformal/btcnet" - "github.com/conformal/btcutil" ) // ExtractPkScriptAddrs returns the type of script, addresses and required diff --git a/address_test.go b/address_test.go index fbd4af76..a60cf3b8 100644 --- a/address_test.go +++ b/address_test.go @@ -8,9 +8,9 @@ import ( "reflect" "testing" + "github.com/btcsuite/btcutil" "github.com/conformal/btcnet" "github.com/conformal/btcscript" - "github.com/conformal/btcutil" ) // decodeHex decodes the passed hex string and returns the resulting bytes. It diff --git a/example_test.go b/example_test.go index 933705c7..d1aa23b7 100644 --- a/example_test.go +++ b/example_test.go @@ -8,9 +8,9 @@ import ( "encoding/hex" "fmt" + "github.com/btcsuite/btcutil" "github.com/conformal/btcnet" "github.com/conformal/btcscript" - "github.com/conformal/btcutil" ) // This example demonstrates creating a script which pays to a bitcoin address. diff --git a/internal_test.go b/internal_test.go index 8d80dcec..97fe92cd 100644 --- a/internal_test.go +++ b/internal_test.go @@ -14,7 +14,7 @@ import ( "strings" "testing" - "github.com/conformal/btcutil" + "github.com/btcsuite/btcutil" "github.com/conformal/btcwire" ) diff --git a/script.go b/script.go index 3ec0f5c9..140c2976 100644 --- a/script.go +++ b/script.go @@ -11,9 +11,9 @@ import ( "fmt" "time" + "github.com/btcsuite/btcutil" "github.com/conformal/btcec" "github.com/conformal/btcnet" - "github.com/conformal/btcutil" "github.com/conformal/btcwire" ) diff --git a/script_test.go b/script_test.go index ec097c57..45e2578c 100644 --- a/script_test.go +++ b/script_test.go @@ -10,10 +10,10 @@ import ( "fmt" "testing" + "github.com/btcsuite/btcutil" "github.com/conformal/btcec" "github.com/conformal/btcnet" "github.com/conformal/btcscript" - "github.com/conformal/btcutil" "github.com/conformal/btcwire" ) From c112c004cffe32b38591c231239dc8c7f5bc3b13 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 16 Jan 2015 09:15:43 -0600 Subject: [PATCH 162/174] Update log test for upstream seelog changes. --- log_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/log_test.go b/log_test.go index ade92316..a96f3e81 100644 --- a/log_test.go +++ b/log_test.go @@ -36,7 +36,7 @@ func TestSetLogWriter(t *testing.T) { name: "use off level", w: os.Stdout, level: "off", - expected: errors.New("Min level can't be greater than max. Got min: 6, max: 5"), + expected: errors.New("min level can't be greater than max. Got min: 6, max: 5"), }, { name: "pass", @@ -52,13 +52,13 @@ func TestSetLogWriter(t *testing.T) { if err != nil { if err.Error() != test.expected.Error() { t.Errorf("SetLogWriter #%d (%s) wrong result\n"+ - "got: %x\nwant: %x", i, test.name, err, + "got: %v\nwant: %v", i, test.name, err, test.expected) } } else { if test.expected != nil { t.Errorf("SetLogWriter #%d (%s) wrong result\n"+ - "got: %x\nwant: %x", i, test.name, err, + "got: %v\nwant: %v", i, test.name, err, test.expected) } } From 6dcc6e5e66ec6a345b59bc8f2262254c106ec7e2 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 16 Jan 2015 09:08:44 -0600 Subject: [PATCH 163/174] Update fastsha256 import paths to new location. --- opcode.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opcode.go b/opcode.go index 053d268e..be1a36ce 100644 --- a/opcode.go +++ b/opcode.go @@ -15,9 +15,9 @@ import ( "golang.org/x/crypto/ripemd160" + "github.com/btcsuite/fastsha256" "github.com/conformal/btcec" "github.com/conformal/btcwire" - "github.com/conformal/fastsha256" ) // An opcode defines the information related to a btcscript opcode. From 6efda349daafa519b91246065acc9ec2ca7cecb9 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 16 Jan 2015 11:18:14 -0600 Subject: [PATCH 164/174] Update btclog import paths to new location. --- log.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/log.go b/log.go index 791bc355..8f7cc5cf 100644 --- a/log.go +++ b/log.go @@ -8,7 +8,7 @@ import ( "errors" "io" - "github.com/conformal/btclog" + "github.com/btcsuite/btclog" ) // log is a logger that is initialized with no output filters. This From 5c52f67b4f3a078d4ee25a44e79287f391c67062 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 16 Jan 2015 15:18:22 -0600 Subject: [PATCH 165/174] Update btcwire import paths to new location. --- internal_test.go | 2 +- opcode.go | 2 +- opcode_test.go | 2 +- script.go | 2 +- script_test.go | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/internal_test.go b/internal_test.go index 97fe92cd..e03c483d 100644 --- a/internal_test.go +++ b/internal_test.go @@ -15,7 +15,7 @@ import ( "testing" "github.com/btcsuite/btcutil" - "github.com/conformal/btcwire" + "github.com/btcsuite/btcwire" ) // this file is present to export some internal interfaces so that we can diff --git a/opcode.go b/opcode.go index be1a36ce..c4f00a1f 100644 --- a/opcode.go +++ b/opcode.go @@ -15,9 +15,9 @@ import ( "golang.org/x/crypto/ripemd160" + "github.com/btcsuite/btcwire" "github.com/btcsuite/fastsha256" "github.com/conformal/btcec" - "github.com/conformal/btcwire" ) // An opcode defines the information related to a btcscript opcode. diff --git a/opcode_test.go b/opcode_test.go index 6bed4c31..81492237 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -8,8 +8,8 @@ import ( "bytes" "testing" + "github.com/btcsuite/btcwire" "github.com/conformal/btcscript" - "github.com/conformal/btcwire" ) // test scripts to test as many opcodes as possible. diff --git a/script.go b/script.go index 140c2976..0a51ac47 100644 --- a/script.go +++ b/script.go @@ -12,9 +12,9 @@ import ( "time" "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcwire" "github.com/conformal/btcec" "github.com/conformal/btcnet" - "github.com/conformal/btcwire" ) var ( diff --git a/script_test.go b/script_test.go index 45e2578c..5e2f1708 100644 --- a/script_test.go +++ b/script_test.go @@ -11,10 +11,10 @@ import ( "testing" "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcwire" "github.com/conformal/btcec" "github.com/conformal/btcnet" "github.com/conformal/btcscript" - "github.com/conformal/btcwire" ) func TestPushedData(t *testing.T) { From f513a56a62016263eb4f6ad51e5d42c76b3aa753 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 16 Jan 2015 17:29:53 -0600 Subject: [PATCH 166/174] Update btcnet import paths to new location. --- address.go | 2 +- address_test.go | 2 +- example_test.go | 2 +- script.go | 2 +- script_test.go | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/address.go b/address.go index e9644482..7f6b9872 100644 --- a/address.go +++ b/address.go @@ -5,8 +5,8 @@ package btcscript import ( + "github.com/btcsuite/btcnet" "github.com/btcsuite/btcutil" - "github.com/conformal/btcnet" ) // ExtractPkScriptAddrs returns the type of script, addresses and required diff --git a/address_test.go b/address_test.go index a60cf3b8..90f42e7c 100644 --- a/address_test.go +++ b/address_test.go @@ -8,8 +8,8 @@ import ( "reflect" "testing" + "github.com/btcsuite/btcnet" "github.com/btcsuite/btcutil" - "github.com/conformal/btcnet" "github.com/conformal/btcscript" ) diff --git a/example_test.go b/example_test.go index d1aa23b7..8286be01 100644 --- a/example_test.go +++ b/example_test.go @@ -8,8 +8,8 @@ import ( "encoding/hex" "fmt" + "github.com/btcsuite/btcnet" "github.com/btcsuite/btcutil" - "github.com/conformal/btcnet" "github.com/conformal/btcscript" ) diff --git a/script.go b/script.go index 0a51ac47..6c8395cb 100644 --- a/script.go +++ b/script.go @@ -11,10 +11,10 @@ import ( "fmt" "time" + "github.com/btcsuite/btcnet" "github.com/btcsuite/btcutil" "github.com/btcsuite/btcwire" "github.com/conformal/btcec" - "github.com/conformal/btcnet" ) var ( diff --git a/script_test.go b/script_test.go index 5e2f1708..14ab8a6e 100644 --- a/script_test.go +++ b/script_test.go @@ -10,10 +10,10 @@ import ( "fmt" "testing" + "github.com/btcsuite/btcnet" "github.com/btcsuite/btcutil" "github.com/btcsuite/btcwire" "github.com/conformal/btcec" - "github.com/conformal/btcnet" "github.com/conformal/btcscript" ) From eb02adfada569144c6a8c4cce1aeefcc269d3acc Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 16 Jan 2015 18:05:06 -0600 Subject: [PATCH 167/174] Update btcec import paths to new location. --- opcode.go | 2 +- script.go | 2 +- script_test.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/opcode.go b/opcode.go index c4f00a1f..ca4fa8ff 100644 --- a/opcode.go +++ b/opcode.go @@ -15,9 +15,9 @@ import ( "golang.org/x/crypto/ripemd160" + "github.com/btcsuite/btcec" "github.com/btcsuite/btcwire" "github.com/btcsuite/fastsha256" - "github.com/conformal/btcec" ) // An opcode defines the information related to a btcscript opcode. diff --git a/script.go b/script.go index 6c8395cb..ddecc5bf 100644 --- a/script.go +++ b/script.go @@ -11,10 +11,10 @@ import ( "fmt" "time" + "github.com/btcsuite/btcec" "github.com/btcsuite/btcnet" "github.com/btcsuite/btcutil" "github.com/btcsuite/btcwire" - "github.com/conformal/btcec" ) var ( diff --git a/script_test.go b/script_test.go index 14ab8a6e..fce5f0b3 100644 --- a/script_test.go +++ b/script_test.go @@ -10,10 +10,10 @@ import ( "fmt" "testing" + "github.com/btcsuite/btcec" "github.com/btcsuite/btcnet" "github.com/btcsuite/btcutil" "github.com/btcsuite/btcwire" - "github.com/conformal/btcec" "github.com/conformal/btcscript" ) From 251d0fc6c47de9a879a77061d311e7dd77804034 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 16 Jan 2015 19:33:51 -0600 Subject: [PATCH 168/174] Update btcscript import paths to new location. --- README.md | 18 +++++++++--------- address_test.go | 2 +- example_test.go | 2 +- log_test.go | 2 +- opcode_test.go | 2 +- script_test.go | 2 +- scriptbuilder_test.go | 2 +- stack_test.go | 2 +- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index db56a016..35340507 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ btcscript ========= -[![Build Status](https://travis-ci.org/conformal/btcscript.png?branch=master)] -(https://travis-ci.org/conformal/btcscript) +[![Build Status](https://travis-ci.org/btcsuite/btcscript.png?branch=master)] +(https://travis-ci.org/btcsuite/btcscript) Package btcscript implements the bitcoin transaction scripts. There is a comprehensive test suite. `test_coverage.txt` contains the current @@ -25,33 +25,33 @@ can be found at https://en.bitcoin.it/wiki/Script ## Documentation -[![GoDoc](https://godoc.org/github.com/conformal/btcscript?status.png)] -(http://godoc.org/github.com/conformal/btcscript) +[![GoDoc](https://godoc.org/github.com/btcsuite/btcscript?status.png)] +(http://godoc.org/github.com/btcsuite/btcscript) Full `go doc` style documentation for the project can be viewed online without installing this package by using the GoDoc site -[here](http://godoc.org/github.com/conformal/btcscript). +[here](http://godoc.org/github.com/btcsuite/btcscript). You can also view the documentation locally once the package is installed with the `godoc` tool by running `godoc -http=":6060"` and pointing your browser to -http://localhost:6060/pkg/github.com/conformal/btcscript +http://localhost:6060/pkg/github.com/btcsuite/btcscript ## Installation ```bash -$ go get github.com/conformal/btcscript +$ go get github.com/btcsuite/btcscript ``` ## Examples * [Standard Pay-to-pubkey-hash Script] - (http://godoc.org/github.com/conformal/btcscript#example-PayToAddrScript) + (http://godoc.org/github.com/btcsuite/btcscript#example-PayToAddrScript) Demonstrates creating a script which pays to a bitcoin address. It also prints the created script hex and uses the DisasmString function to display the disassembled script. * [Extracting Details from Standard Scripts] - (http://godoc.org/github.com/conformal/btcscript#example-ExtractPkScriptAddrs) + (http://godoc.org/github.com/btcsuite/btcscript#example-ExtractPkScriptAddrs) Demonstrates extracting information from a standard public key script. ## TODO diff --git a/address_test.go b/address_test.go index 90f42e7c..36598e88 100644 --- a/address_test.go +++ b/address_test.go @@ -9,8 +9,8 @@ import ( "testing" "github.com/btcsuite/btcnet" + "github.com/btcsuite/btcscript" "github.com/btcsuite/btcutil" - "github.com/conformal/btcscript" ) // decodeHex decodes the passed hex string and returns the resulting bytes. It diff --git a/example_test.go b/example_test.go index 8286be01..a798e288 100644 --- a/example_test.go +++ b/example_test.go @@ -9,8 +9,8 @@ import ( "fmt" "github.com/btcsuite/btcnet" + "github.com/btcsuite/btcscript" "github.com/btcsuite/btcutil" - "github.com/conformal/btcscript" ) // This example demonstrates creating a script which pays to a bitcoin address. diff --git a/log_test.go b/log_test.go index a96f3e81..3b740de1 100644 --- a/log_test.go +++ b/log_test.go @@ -10,7 +10,7 @@ import ( "os" "testing" - "github.com/conformal/btcscript" + "github.com/btcsuite/btcscript" ) func TestSetLogWriter(t *testing.T) { diff --git a/opcode_test.go b/opcode_test.go index 81492237..0de1b7dd 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -8,8 +8,8 @@ import ( "bytes" "testing" + "github.com/btcsuite/btcscript" "github.com/btcsuite/btcwire" - "github.com/conformal/btcscript" ) // test scripts to test as many opcodes as possible. diff --git a/script_test.go b/script_test.go index fce5f0b3..fbb08147 100644 --- a/script_test.go +++ b/script_test.go @@ -12,9 +12,9 @@ import ( "github.com/btcsuite/btcec" "github.com/btcsuite/btcnet" + "github.com/btcsuite/btcscript" "github.com/btcsuite/btcutil" "github.com/btcsuite/btcwire" - "github.com/conformal/btcscript" ) func TestPushedData(t *testing.T) { diff --git a/scriptbuilder_test.go b/scriptbuilder_test.go index 41fd2e65..c5989494 100644 --- a/scriptbuilder_test.go +++ b/scriptbuilder_test.go @@ -8,7 +8,7 @@ import ( "bytes" "testing" - "github.com/conformal/btcscript" + "github.com/btcsuite/btcscript" ) // TestScriptBuilderAddOp tests that pushing opcodes to a script via the diff --git a/stack_test.go b/stack_test.go index 2448ebf6..df58c28f 100644 --- a/stack_test.go +++ b/stack_test.go @@ -11,7 +11,7 @@ import ( "math/big" "testing" - "github.com/conformal/btcscript" + "github.com/btcsuite/btcscript" ) type stackTest struct { From af5cbe4b4f0665a2c79619e51b40e17c33b1889c Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Sat, 20 Dec 2014 01:34:39 -0600 Subject: [PATCH 169/174] Update script builder for BIP0062 and enforce limits. BIP0062 defines specific rules and canonical encodings for data pushes. The existing script builder code already conformed to all but one of the canonical data push rules that was added after it was originally implemented (adding a single byte of 0x81 must be converted to OP_1NEGATE). This commit implements that case and expands the existing tests to explicitly cover all cases mentioned in BIP0062. In addition, as a part of this change, the AddData function has been modified so that any attempt to push more than the maximum script element size bytes (520) in one push or any pushes the would cause the script to exceed the maximum script bytes allowed by the script engine (10000) will result in the final call to the Script function to only return the script up to the point of the first error along with the error. This change should have little effect on existing callers since they are almost positively not creating scripts which violate these rules as they could never be executed, however it does mean they need to check the new error return. Since the regression tests intentionally need to be able to exceed that limit, a new function named AddFullData has been added which does not enforce the limits, but still provides canonical encoding of the pushed data. Note that this commit does not affect consensus rules nor modify the script engine. Also, the tests have been marked so they can run in parallel. --- internal_test.go | 8 +- script.go | 29 +++-- script_test.go | 54 +++++--- scriptbuilder.go | 178 ++++++++++++++++++++++++-- scriptbuilder_test.go | 283 +++++++++++++++++++++++++++++++++++++----- 5 files changed, 480 insertions(+), 72 deletions(-) diff --git a/internal_test.go b/internal_test.go index e03c483d..5886bb8d 100644 --- a/internal_test.go +++ b/internal_test.go @@ -18,6 +18,10 @@ import ( "github.com/btcsuite/btcwire" ) +// TstMaxScriptSize makes the internal maxScriptSize constant available to the +// test package. +const TstMaxScriptSize = maxScriptSize + // this file is present to export some internal interfaces so that we can // test them reliably. @@ -3781,7 +3785,7 @@ func ParseShortForm(script string) ([]byte, error) { builder.script = append(builder.script, bts...) } else if len(tok) >= 2 && tok[0] == '\'' && tok[len(tok)-1] == '\'' { - builder.AddData([]byte(tok[1 : len(tok)-1])) + builder.AddFullData([]byte(tok[1 : len(tok)-1])) } else if opcode, ok := ops[tok]; ok { builder.AddOp(opcode.value) } else { @@ -3789,7 +3793,7 @@ func ParseShortForm(script string) ([]byte, error) { } } - return builder.Script(), nil + return builder.Script() } func TestBitcoindInvalidTests(t *testing.T) { diff --git a/script.go b/script.go index ddecc5bf..e6be9339 100644 --- a/script.go +++ b/script.go @@ -1019,7 +1019,7 @@ func getSigOpCount(pops []parsedOpcode, precise bool) int { // payToPubKeyHashScript creates a new script to pay a transaction // output to a 20-byte pubkey hash. It is expected that the input is a valid // hash. -func payToPubKeyHashScript(pubKeyHash []byte) []byte { +func payToPubKeyHashScript(pubKeyHash []byte) ([]byte, error) { return NewScriptBuilder().AddOp(OP_DUP).AddOp(OP_HASH160). AddData(pubKeyHash).AddOp(OP_EQUALVERIFY).AddOp(OP_CHECKSIG). Script() @@ -1027,14 +1027,14 @@ func payToPubKeyHashScript(pubKeyHash []byte) []byte { // payToScriptHashScript creates a new script to pay a transaction output to a // script hash. It is expected that the input is a valid hash. -func payToScriptHashScript(scriptHash []byte) []byte { +func payToScriptHashScript(scriptHash []byte) ([]byte, error) { return NewScriptBuilder().AddOp(OP_HASH160).AddData(scriptHash). AddOp(OP_EQUAL).Script() } // payToPubkeyScript creates a new script to pay a transaction output to a // public key. It is expected that the input is a valid pubkey. -func payToPubKeyScript(serializedPubKey []byte) []byte { +func payToPubKeyScript(serializedPubKey []byte) ([]byte, error) { return NewScriptBuilder().AddData(serializedPubKey). AddOp(OP_CHECKSIG).Script() } @@ -1047,19 +1047,19 @@ func PayToAddrScript(addr btcutil.Address) ([]byte, error) { if addr == nil { return nil, ErrUnsupportedAddress } - return payToPubKeyHashScript(addr.ScriptAddress()), nil + return payToPubKeyHashScript(addr.ScriptAddress()) case *btcutil.AddressScriptHash: if addr == nil { return nil, ErrUnsupportedAddress } - return payToScriptHashScript(addr.ScriptAddress()), nil + return payToScriptHashScript(addr.ScriptAddress()) case *btcutil.AddressPubKey: if addr == nil { return nil, ErrUnsupportedAddress } - return payToPubKeyScript(addr.ScriptAddress()), nil + return payToPubKeyScript(addr.ScriptAddress()) } return nil, ErrUnsupportedAddress @@ -1085,7 +1085,7 @@ func MultiSigScript(pubkeys []*btcutil.AddressPubKey, nrequired int) ([]byte, er builder.AddInt64(int64(len(pubkeys))) builder.AddOp(OP_CHECKMULTISIG) - return builder.Script(), nil + return builder.Script() } // SignatureScript creates an input signature script for tx to spend @@ -1111,7 +1111,7 @@ func SignatureScript(tx *btcwire.MsgTx, idx int, subscript []byte, hashType SigH pkData = pk.SerializeUncompressed() } - return NewScriptBuilder().AddData(sig).AddData(pkData).Script(), nil + return NewScriptBuilder().AddData(sig).AddData(pkData).Script() } // RawTxInSignature returns the serialized ECDSA signature for the input @@ -1137,7 +1137,7 @@ func p2pkSignatureScript(tx *btcwire.MsgTx, idx int, subScript []byte, hashType return nil, err } - return NewScriptBuilder().AddData(sig).Script(), nil + return NewScriptBuilder().AddData(sig).Script() } // signMultiSig signs as many of the outputs in the provided multisig script as @@ -1169,7 +1169,8 @@ func signMultiSig(tx *btcwire.MsgTx, idx int, subScript []byte, hashType SigHash } - return builder.Script(), signed == nRequired + script, _ := builder.Script() + return script, signed == nRequired } func sign(net *btcnet.Params, tx *btcwire.MsgTx, idx int, subScript []byte, @@ -1277,7 +1278,8 @@ func mergeScripts(net *btcnet.Params, tx *btcwire.MsgTx, idx int, builder := NewScriptBuilder() builder.script = mergedScript builder.AddData(script) - return builder.Script() + finalScript, _ := builder.Script() + return finalScript case MultiSigTy: return mergeMultiSig(tx, idx, addresses, nRequired, pkScript, sigScript, prevScript) @@ -1407,7 +1409,8 @@ sigLoop: builder.AddOp(OP_0) } - return builder.Script() + script, _ := builder.Script() + return script } // KeyDB is an interface type provided to SignTxOutput, it encapsulates @@ -1470,7 +1473,7 @@ func SignTxOutput(net *btcnet.Params, tx *btcwire.MsgTx, idx int, builder.script = realSigScript builder.AddData(sigScript) - sigScript = builder.Script() + sigScript, _ = builder.Script() // TODO keep a copy of the script for merging. } diff --git a/script_test.go b/script_test.go index fbb08147..8ff919a7 100644 --- a/script_test.go +++ b/script_test.go @@ -17,6 +17,18 @@ import ( "github.com/btcsuite/btcwire" ) +// builderScript is a convenience function which is used in the tests. It +// allows access to the script from a known good script built with the builder. +// Any errors are converted to a panic since it is only, and must only, be used +// with hard coded, and therefore, known good, scripts. +func builderScript(builder *btcscript.ScriptBuilder) []byte { + script, err := builder.Script() + if err != nil { + panic(err) + } + return script +} + func TestPushedData(t *testing.T) { var tests = []struct { in []byte @@ -29,7 +41,7 @@ func TestPushedData(t *testing.T) { true, }, { - btcscript.NewScriptBuilder().AddInt64(16777216).AddInt64(10000000).Script(), + builderScript(btcscript.NewScriptBuilder().AddInt64(16777216).AddInt64(10000000)), [][]byte{ {0x00, 0x00, 0x00, 0x01}, // 16777216 {0x80, 0x96, 0x98, 0x00}, // 10000000 @@ -37,9 +49,9 @@ func TestPushedData(t *testing.T) { true, }, { - btcscript.NewScriptBuilder().AddOp(btcscript.OP_DUP).AddOp(btcscript.OP_HASH160). + builderScript(btcscript.NewScriptBuilder().AddOp(btcscript.OP_DUP).AddOp(btcscript.OP_HASH160). AddData([]byte("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem")).AddOp(btcscript.OP_EQUALVERIFY). - AddOp(btcscript.OP_CHECKSIG).Script(), + AddOp(btcscript.OP_CHECKSIG)), [][]byte{ // 17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem { @@ -52,8 +64,8 @@ func TestPushedData(t *testing.T) { true, }, { - btcscript.NewScriptBuilder().AddOp(btcscript.OP_PUSHDATA4).AddInt64(1000). - AddOp(btcscript.OP_EQUAL).Script(), + builderScript(btcscript.NewScriptBuilder().AddOp(btcscript.OP_PUSHDATA4).AddInt64(1000). + AddOp(btcscript.OP_EQUAL)), [][]byte{}, false, }, @@ -78,25 +90,37 @@ func TestPushedData(t *testing.T) { } func TestStandardPushes(t *testing.T) { - for i := 0; i < 1000; i++ { + for i := 0; i < 65535; i++ { builder := btcscript.NewScriptBuilder() builder.AddInt64(int64(i)) - if result := btcscript.IsPushOnlyScript(builder.Script()); !result { - t.Errorf("StandardPushesTests IsPushOnlyScript test #%d failed: %x\n", i, builder.Script()) + script, err := builder.Script() + if err != nil { + t.Errorf("StandardPushesTests test #%d unexpected error: %v\n", i, err) + continue } - if result := btcscript.HasCanonicalPushes(builder.Script()); !result { - t.Errorf("StandardPushesTests HasCanonicalPushes test #%d failed: %x\n", i, builder.Script()) + if result := btcscript.IsPushOnlyScript(script); !result { + t.Errorf("StandardPushesTests IsPushOnlyScript test #%d failed: %x\n", i, script) + continue + } + if result := btcscript.HasCanonicalPushes(script); !result { + t.Errorf("StandardPushesTests HasCanonicalPushes test #%d failed: %x\n", i, script) continue } } - for i := 0; i < 1000; i++ { + for i := 0; i <= btcscript.MaxScriptElementSize; i++ { builder := btcscript.NewScriptBuilder() builder.AddData(bytes.Repeat([]byte{0x49}, i)) - if result := btcscript.IsPushOnlyScript(builder.Script()); !result { - t.Errorf("StandardPushesTests IsPushOnlyScript test #%d failed: %x\n", i, builder.Script()) + script, err := builder.Script() + if err != nil { + t.Errorf("StandardPushesTests test #%d unexpected error: %v\n", i, err) + continue } - if result := btcscript.HasCanonicalPushes(builder.Script()); !result { - t.Errorf("StandardPushesTests HasCanonicalPushes test #%d failed: %x\n", i, builder.Script()) + if result := btcscript.IsPushOnlyScript(script); !result { + t.Errorf("StandardPushesTests IsPushOnlyScript test #%d failed: %x\n", i, script) + continue + } + if result := btcscript.HasCanonicalPushes(script); !result { + t.Errorf("StandardPushesTests HasCanonicalPushes test #%d failed: %x\n", i, script) continue } } diff --git a/scriptbuilder.go b/scriptbuilder.go index e34008bb..566189df 100644 --- a/scriptbuilder.go +++ b/scriptbuilder.go @@ -6,6 +6,7 @@ package btcscript import ( "encoding/binary" + "fmt" "math/big" ) @@ -18,9 +19,21 @@ const ( defaultScriptAlloc = 500 ) +// ErrScriptNotCanonical identifies a non-canonical script. The caller can use +// a type assertion to detect this error type. +type ErrScriptNotCanonical string + +// Error implements the error interface. +func (e ErrScriptNotCanonical) Error() string { + return string(e) +} + // ScriptBuilder provides a facility for building custom scripts. It allows -// you to push opcodes, ints, and data while respecting canonical encoding. It -// does not ensure the script will execute correctly. +// you to push opcodes, ints, and data while respecting canonical encoding. In +// general it does not ensure the script will execute correctly, however any +// data pushes which would exceed the maximum allowed script engine limits and +// are therefore guaranteed not to execute will not be pushed and will result in +// the Script function returning an error. // // For example, the following would build a 2-of-3 multisig script for usage in // a pay-to-script-hash (although in this situation MultiSigScript() would be a @@ -29,21 +42,70 @@ const ( // builder.AddOp(btcscript.OP_2).AddData(pubKey1).AddData(pubKey2) // builder.AddData(pubKey3).AddOp(btcscript.OP_3) // builder.AddOp(btcscript.OP_CHECKMULTISIG) -// fmt.Printf("Final multi-sig script: %x\n", builder.Script()) +// script, err := builder.Script() +// if err != nil { +// // Handle the error. +// return +// } +// fmt.Printf("Final multi-sig script: %x\n", script) type ScriptBuilder struct { script []byte + err error } -// AddOp pushes the passed opcode to the end of the script. +// AddOp pushes the passed opcode to the end of the script. The script will not +// be modified if pushing the opcode would cause the script to exceed the +// maximum allowed script engine size. func (b *ScriptBuilder) AddOp(opcode byte) *ScriptBuilder { + if b.err != nil { + return b + } + + // Pushes that would cause the script to exceed the largest allowed + // script size would result in a non-canonical script. + if len(b.script)+1 > maxScriptSize { + str := fmt.Sprintf("adding an opcode would exceed the maximum "+ + "allowed canonical script length of %d", maxScriptSize) + b.err = ErrScriptNotCanonical(str) + return b + } + b.script = append(b.script, opcode) return b } -// AddData pushes the passed data to the end of the script. It automatically -// chooses canonical opcodes depending on the length of the data. A zero length -// buffer will lead to a push of empty data onto the stack. -func (b *ScriptBuilder) AddData(data []byte) *ScriptBuilder { +// canonicalDataSize returns the number of bytes the canonical encoding of the +// data will take. +func canonicalDataSize(data []byte) int { + dataLen := len(data) + + // When the data consists of a single number that can be represented + // by one of the "small integer" opcodes, that opcode will be instead + // of a data push opcode followed by the number. + if dataLen == 0 { + return 1 + } else if dataLen == 1 && data[0] <= 16 { + return 1 + } else if dataLen == 1 && data[0] == 0x81 { + return 1 + } + + if dataLen < OP_PUSHDATA1 { + return 1 + dataLen + } else if dataLen <= 0xff { + return 2 + dataLen + } else if dataLen <= 0xffff { + return 3 + dataLen + } + + return 5 + dataLen +} + +// addData is the internal function that actually pushes the passed data to the +// end of the script. It automatically chooses canonical opcodes depending on +// the length of the data. A zero length buffer will lead to a push of empty +// data onto the stack (OP_0). No data limits are enforced with this function. +func (b *ScriptBuilder) addData(data []byte) *ScriptBuilder { dataLen := len(data) // When the data consists of a single number that can be represented @@ -55,6 +117,9 @@ func (b *ScriptBuilder) AddData(data []byte) *ScriptBuilder { } else if dataLen == 1 && data[0] <= 16 { b.script = append(b.script, byte((OP_1-1)+data[0])) return b + } else if dataLen == 1 && data[0] == 0x81 { + b.script = append(b.script, byte(OP_1NEGATE)) + return b } // Use one of the OP_DATA_# opcodes if the length of the data is small @@ -83,8 +148,76 @@ func (b *ScriptBuilder) AddData(data []byte) *ScriptBuilder { return b } -// AddInt64 pushes the passed integer to the end of the script. +// AddFullData should not typically be used by ordinary users as it does not +// include the checks which prevent data pushes larger than the maximum allowed +// sizes which leads to scripts that can't be executed. This is provided for +// testing purposes such as regression tests where sizes are intentionally made +// larger than allowed. +// +// Use AddData instead. +func (b *ScriptBuilder) AddFullData(data []byte) *ScriptBuilder { + if b.err != nil { + return b + } + + return b.addData(data) +} + +// AddData pushes the passed data to the end of the script. It automatically +// chooses canonical opcodes depending on the length of the data. A zero length +// buffer will lead to a push of empty data onto the stack (OP_0) and any push +// of data greater than MaxScriptElementSize will not modify the script since +// that is not allowed by the script engine. Also, the script will not be +// modified if pushing the data would cause the script to exceed the maximum +// allowed script engine size. +func (b *ScriptBuilder) AddData(data []byte) *ScriptBuilder { + if b.err != nil { + return b + } + + // Pushes that would cause the script to exceed the largest allowed + // script size would result in a non-canonical script. + dataSize := canonicalDataSize(data) + if len(b.script)+dataSize > maxScriptSize { + str := fmt.Sprintf("adding %d bytes of data would exceed the "+ + "maximum allowed canonical script length of %d", + dataSize, maxScriptSize) + b.err = ErrScriptNotCanonical(str) + return b + } + + // Pushes larger than the max script element size would result in a + // script that is not canonical. + dataLen := len(data) + if dataLen > MaxScriptElementSize { + str := fmt.Sprintf("adding a data element of %d bytes would "+ + "exceed the maximum allowed script element size of %d", + dataLen, maxScriptSize) + b.err = ErrScriptNotCanonical(str) + return b + } + + return b.addData(data) +} + +// AddInt64 pushes the passed integer to the end of the script. The script will +// not be modified if pushing the data would cause the script to exceed the +// maximum allowed script engine size. func (b *ScriptBuilder) AddInt64(val int64) *ScriptBuilder { + if b.err != nil { + return b + } + + // Pushes that would cause the script to exceed the largest allowed + // script size would result in a non-canonical script. + if len(b.script)+1 > maxScriptSize { + str := fmt.Sprintf("adding an integer would exceed the "+ + "maximum allow canonical script length of %d", + maxScriptSize) + b.err = ErrScriptNotCanonical(str) + return b + } + // Fast path for small integers and OP_1NEGATE. if val == 0 { b.script = append(b.script, OP_0) @@ -98,8 +231,24 @@ func (b *ScriptBuilder) AddInt64(val int64) *ScriptBuilder { return b.AddData(fromInt(new(big.Int).SetInt64(val))) } -// AddUint64 pushes the passed integer to the end of the script. +// AddUint64 pushes the passed integer to the end of the script. The script +// will not be modified if pushing the data would cause the script to +// exceed the maximum allowed script engine size. func (b *ScriptBuilder) AddUint64(val uint64) *ScriptBuilder { + if b.err != nil { + return b + } + + // Pushes that would cause the script to exceed the largest allowed + // script size would result in a non-canonical script. + if len(b.script)+1 > maxScriptSize { + str := fmt.Sprintf("adding an unsigned integer would exceed "+ + "the maximum allow canonical script length of %d", + maxScriptSize) + b.err = ErrScriptNotCanonical(str) + return b + } + // Fast path for small integers. if val == 0 { b.script = append(b.script, OP_0) @@ -116,12 +265,15 @@ func (b *ScriptBuilder) AddUint64(val uint64) *ScriptBuilder { // Reset resets the script so it has no content. func (b *ScriptBuilder) Reset() *ScriptBuilder { b.script = b.script[0:0] + b.err = nil return b } -// Script returns the currently built script. -func (b *ScriptBuilder) Script() []byte { - return b.script +// Script returns the currently built script. When any errors occured while +// building the script, the script will be returned up the point of the first +// error along with the error. +func (b *ScriptBuilder) Script() ([]byte, error) { + return b.script, b.err } // NewScriptBuilder returns a new instance of a script builder. See diff --git a/scriptbuilder_test.go b/scriptbuilder_test.go index c5989494..265ba882 100644 --- a/scriptbuilder_test.go +++ b/scriptbuilder_test.go @@ -14,6 +14,8 @@ import ( // TestScriptBuilderAddOp tests that pushing opcodes to a script via the // ScriptBuilder API works as expected. func TestScriptBuilderAddOp(t *testing.T) { + t.Parallel() + tests := []struct { name string opcodes []byte @@ -43,7 +45,12 @@ func TestScriptBuilderAddOp(t *testing.T) { for _, opcode := range test.opcodes { builder.AddOp(opcode) } - result := builder.Script() + result, err := builder.Script() + if err != nil { + t.Errorf("ScriptBuilder.AddOp #%d (%s) unexpected "+ + "error: %v", i, test.name, err) + continue + } if !bytes.Equal(result, test.expected) { t.Errorf("ScriptBuilder.AddOp #%d (%s) wrong result\n"+ "got: %x\nwant: %x", i, test.name, result, @@ -56,6 +63,8 @@ func TestScriptBuilderAddOp(t *testing.T) { // TestScriptBuilderAddInt64 tests that pushing signed integers to a script via // the ScriptBuilder API works as expected. func TestScriptBuilderAddInt64(t *testing.T) { + t.Parallel() + tests := []struct { name string val int64 @@ -105,7 +114,12 @@ func TestScriptBuilderAddInt64(t *testing.T) { t.Logf("Running %d tests", len(tests)) for i, test := range tests { builder.Reset().AddInt64(test.val) - result := builder.Script() + result, err := builder.Script() + if err != nil { + t.Errorf("ScriptBuilder.AddInt64 #%d (%s) unexpected "+ + "error: %v", i, test.name, err) + continue + } if !bytes.Equal(result, test.expected) { t.Errorf("ScriptBuilder.AddInt64 #%d (%s) wrong result\n"+ "got: %x\nwant: %x", i, test.name, result, @@ -118,6 +132,8 @@ func TestScriptBuilderAddInt64(t *testing.T) { // TestScriptBuilderAddUint64 tests that pushing unsigned integers to a script // via the ScriptBuilder API works as expected. func TestScriptBuilderAddUint64(t *testing.T) { + t.Parallel() + tests := []struct { name string val uint64 @@ -154,7 +170,12 @@ func TestScriptBuilderAddUint64(t *testing.T) { t.Logf("Running %d tests", len(tests)) for i, test := range tests { builder.Reset().AddUint64(test.val) - result := builder.Script() + result, err := builder.Script() + if err != nil { + t.Errorf("ScriptBuilder.AddUint64 #%d (%s) unexpected "+ + "error: %v", err) + continue + } if !bytes.Equal(result, test.expected) { t.Errorf("ScriptBuilder.AddUint64 #%d (%s) wrong result\n"+ "got: %x\nwant: %x", i, test.name, result, @@ -165,33 +186,48 @@ func TestScriptBuilderAddUint64(t *testing.T) { } // TestScriptBuilderAddData tests that pushing data to a script via the -// ScriptBuilder API works as expected. +// ScriptBuilder API works as expected and conforms to BIP0062. func TestScriptBuilderAddData(t *testing.T) { + t.Parallel() + tests := []struct { name string data []byte expected []byte + useFull bool // use AddFullData instead of AddData. }{ - // Start off with the small ints to ensure canonical encoding. - {name: "push small int 0", data: []byte{0}, expected: []byte{btcscript.OP_0}}, - {name: "push small int 1", data: []byte{1}, expected: []byte{btcscript.OP_1}}, - {name: "push small int 2", data: []byte{2}, expected: []byte{btcscript.OP_2}}, - {name: "push small int 3", data: []byte{3}, expected: []byte{btcscript.OP_3}}, - {name: "push small int 4", data: []byte{4}, expected: []byte{btcscript.OP_4}}, - {name: "push small int 5", data: []byte{5}, expected: []byte{btcscript.OP_5}}, - {name: "push small int 6", data: []byte{6}, expected: []byte{btcscript.OP_6}}, - {name: "push small int 7", data: []byte{7}, expected: []byte{btcscript.OP_7}}, - {name: "push small int 8", data: []byte{8}, expected: []byte{btcscript.OP_8}}, - {name: "push small int 9", data: []byte{9}, expected: []byte{btcscript.OP_9}}, - {name: "push small int 10", data: []byte{10}, expected: []byte{btcscript.OP_10}}, - {name: "push small int 11", data: []byte{11}, expected: []byte{btcscript.OP_11}}, - {name: "push small int 12", data: []byte{12}, expected: []byte{btcscript.OP_12}}, - {name: "push small int 13", data: []byte{13}, expected: []byte{btcscript.OP_13}}, - {name: "push small int 14", data: []byte{14}, expected: []byte{btcscript.OP_14}}, - {name: "push small int 15", data: []byte{15}, expected: []byte{btcscript.OP_15}}, - {name: "push small int 16", data: []byte{16}, expected: []byte{btcscript.OP_16}}, + // BIP0062: Pushing an empty byte sequence must use OP_0. + {name: "push empty byte sequence", data: []byte{}, expected: []byte{btcscript.OP_0}}, + {name: "push 1 byte 0x00", data: []byte{0x00}, expected: []byte{btcscript.OP_0}}, - // 1-byte data push opcodes. + // BIP0062: Pushing a 1-byte sequence of byte 0x01 through 0x10 must use OP_n. + {name: "push 1 byte 0x01", data: []byte{0x01}, expected: []byte{btcscript.OP_1}}, + {name: "push 1 byte 0x02", data: []byte{0x02}, expected: []byte{btcscript.OP_2}}, + {name: "push 1 byte 0x03", data: []byte{0x03}, expected: []byte{btcscript.OP_3}}, + {name: "push 1 byte 0x04", data: []byte{0x04}, expected: []byte{btcscript.OP_4}}, + {name: "push 1 byte 0x05", data: []byte{0x05}, expected: []byte{btcscript.OP_5}}, + {name: "push 1 byte 0x06", data: []byte{0x06}, expected: []byte{btcscript.OP_6}}, + {name: "push 1 byte 0x07", data: []byte{0x07}, expected: []byte{btcscript.OP_7}}, + {name: "push 1 byte 0x08", data: []byte{0x08}, expected: []byte{btcscript.OP_8}}, + {name: "push 1 byte 0x09", data: []byte{0x09}, expected: []byte{btcscript.OP_9}}, + {name: "push 1 byte 0x0a", data: []byte{0x0a}, expected: []byte{btcscript.OP_10}}, + {name: "push 1 byte 0x0b", data: []byte{0x0b}, expected: []byte{btcscript.OP_11}}, + {name: "push 1 byte 0x0c", data: []byte{0x0c}, expected: []byte{btcscript.OP_12}}, + {name: "push 1 byte 0x0d", data: []byte{0x0d}, expected: []byte{btcscript.OP_13}}, + {name: "push 1 byte 0x0e", data: []byte{0x0e}, expected: []byte{btcscript.OP_14}}, + {name: "push 1 byte 0x0f", data: []byte{0x0f}, expected: []byte{btcscript.OP_15}}, + {name: "push 1 byte 0x10", data: []byte{0x10}, expected: []byte{btcscript.OP_16}}, + + // BIP0062: Pushing the byte 0x81 must use OP_1NEGATE. + {name: "push 1 byte 0x81", data: []byte{0x81}, expected: []byte{btcscript.OP_1NEGATE}}, + + // BIP0062: Pushing any other byte sequence up to 75 bytes must + // use the normal data push (opcode byte n, with n the number of + // bytes, followed n bytes of data being pushed). + {name: "push 1 byte 0x11", data: []byte{0x11}, expected: []byte{btcscript.OP_DATA_1, 0x11}}, + {name: "push 1 byte 0x80", data: []byte{0x80}, expected: []byte{btcscript.OP_DATA_1, 0x80}}, + {name: "push 1 byte 0x82", data: []byte{0x82}, expected: []byte{btcscript.OP_DATA_1, 0x82}}, + {name: "push 1 byte 0xff", data: []byte{0xff}, expected: []byte{btcscript.OP_DATA_1, 0xff}}, { name: "push data len 17", data: bytes.Repeat([]byte{0x49}, 17), @@ -203,7 +239,7 @@ func TestScriptBuilderAddData(t *testing.T) { expected: append([]byte{btcscript.OP_DATA_75}, bytes.Repeat([]byte{0x49}, 75)...), }, - // 2-byte data push via OP_PUSHDATA_1. + // BIP0062: Pushing 76 to 255 bytes must use OP_PUSHDATA1. { name: "push data len 76", data: bytes.Repeat([]byte{0x49}, 76), @@ -215,31 +251,67 @@ func TestScriptBuilderAddData(t *testing.T) { expected: append([]byte{btcscript.OP_PUSHDATA1, 255}, bytes.Repeat([]byte{0x49}, 255)...), }, - // 3-byte data push via OP_PUSHDATA_2. + // BIP0062: Pushing 256 to 520 bytes must use OP_PUSHDATA2. { name: "push data len 256", data: bytes.Repeat([]byte{0x49}, 256), expected: append([]byte{btcscript.OP_PUSHDATA2, 0, 1}, bytes.Repeat([]byte{0x49}, 256)...), }, { - name: "push data len 32767", + name: "push data len 520", + data: bytes.Repeat([]byte{0x49}, 520), + expected: append([]byte{btcscript.OP_PUSHDATA2, 0x08, 0x02}, bytes.Repeat([]byte{0x49}, 520)...), + }, + + // BIP0062: OP_PUSHDATA4 can never be used, as pushes over 520 + // bytes are not allowed, and those below can be done using + // other operators. + { + name: "push data len 521", + data: bytes.Repeat([]byte{0x49}, 521), + expected: []byte{}, + }, + { + name: "push data len 32767 (canonical)", + data: bytes.Repeat([]byte{0x49}, 32767), + expected: []byte{}, + }, + { + name: "push data len 65536 (canonical)", + data: bytes.Repeat([]byte{0x49}, 65536), + expected: []byte{}, + }, + + // Additional tests for the PushFullData function that + // intentionally allows data pushes to exceed the limit for + // regression testing purposes. + + // 3-byte data push via OP_PUSHDATA_2. + { + name: "push data len 32767 (non-canonical)", data: bytes.Repeat([]byte{0x49}, 32767), expected: append([]byte{btcscript.OP_PUSHDATA2, 255, 127}, bytes.Repeat([]byte{0x49}, 32767)...), + useFull: true, }, // 5-byte data push via OP_PUSHDATA_4. { - name: "push data len 65536", + name: "push data len 65536 (non-canonical)", data: bytes.Repeat([]byte{0x49}, 65536), expected: append([]byte{btcscript.OP_PUSHDATA4, 0, 0, 1, 0}, bytes.Repeat([]byte{0x49}, 65536)...), + useFull: true, }, } builder := btcscript.NewScriptBuilder() t.Logf("Running %d tests", len(tests)) for i, test := range tests { - builder.Reset().AddData(test.data) - result := builder.Script() + if !test.useFull { + builder.Reset().AddData(test.data) + } else { + builder.Reset().AddFullData(test.data) + } + result, _ := builder.Script() if !bytes.Equal(result, test.expected) { t.Errorf("ScriptBuilder.AddData #%d (%s) wrong result\n"+ "got: %x\nwant: %x", i, test.name, result, @@ -248,3 +320,156 @@ func TestScriptBuilderAddData(t *testing.T) { } } } + +// TestExceedMaxScriptSize ensures that all of the functions that can be used +// to add data to a script don't allow the script to exceed the max allowed +// size. +func TestExceedMaxScriptSize(t *testing.T) { + t.Parallel() + + // Start off by constructing a max size script. + maxScriptSize := btcscript.TstMaxScriptSize + builder := btcscript.NewScriptBuilder() + builder.Reset().AddFullData(make([]byte, maxScriptSize-3)) + origScript, err := builder.Script() + if err != nil { + t.Fatalf("Unexpected error for max size script: %v", err) + } + + // Ensure adding data that would exceed the maximum size of the script + // does not add the data. + script, err := builder.AddData([]byte{0x00}).Script() + if _, ok := err.(btcscript.ErrScriptNotCanonical); !ok || err == nil { + t.Fatalf("ScriptBuilder.AddData allowed exceeding max script "+ + "size: %v", len(script)) + } + if !bytes.Equal(script, origScript) { + t.Fatalf("ScriptBuilder.AddData unexpected modified script - "+ + "got len %d, want len %d", len(script), len(origScript)) + } + + // Ensure adding an opcode that would exceed the maximum size of the + // script does not add the data. + builder.Reset().AddFullData(make([]byte, maxScriptSize-3)) + script, err = builder.AddOp(btcscript.OP_0).Script() + if _, ok := err.(btcscript.ErrScriptNotCanonical); !ok || err == nil { + t.Fatalf("ScriptBuilder.AddOp unexpected modified script - "+ + "got len %d, want len %d", len(script), len(origScript)) + } + if !bytes.Equal(script, origScript) { + t.Fatalf("ScriptBuilder.AddOp unexpected modified script - "+ + "got len %d, want len %d", len(script), len(origScript)) + } + + // Ensure adding an integer that would exceed the maximum size of the + // script does not add the data. + builder.Reset().AddFullData(make([]byte, maxScriptSize-3)) + script, err = builder.AddInt64(0).Script() + if _, ok := err.(btcscript.ErrScriptNotCanonical); !ok || err == nil { + t.Fatalf("ScriptBuilder.AddInt64 unexpected modified script - "+ + "got len %d, want len %d", len(script), len(origScript)) + } + if !bytes.Equal(script, origScript) { + t.Fatalf("ScriptBuilder.AddInt64 unexpected modified script - "+ + "got len %d, want len %d", len(script), len(origScript)) + } + + // Ensure adding an unsigned integer that would exceed the maximum size + // of the script does not add the data. + builder.Reset().AddFullData(make([]byte, maxScriptSize-3)) + script, err = builder.AddUint64(0).Script() + if _, ok := err.(btcscript.ErrScriptNotCanonical); !ok || err == nil { + t.Fatalf("ScriptBuilder.AddUint64 unexpected modified script - "+ + "got len %d, want len %d", len(script), len(origScript)) + } + if !bytes.Equal(script, origScript) { + t.Fatalf("ScriptBuilder.AddUint64 unexpected modified script - "+ + "got len %d, want len %d", len(script), len(origScript)) + } +} + +// TestErroredScript ensures that all of the functions that can be used to add +// data to a script don't modify the script once an error has happened. +func TestErroredScript(t *testing.T) { + t.Parallel() + + // Start off by constructing a near max size script that has enough + // space left to add each data type without an error and force an + // initial error condition. + maxScriptSize := btcscript.TstMaxScriptSize + builder := btcscript.NewScriptBuilder() + builder.Reset().AddFullData(make([]byte, maxScriptSize-8)) + origScript, err := builder.Script() + if err != nil { + t.Fatalf("ScriptBuilder.AddFullData unexpected error: %v", err) + } + script, err := builder.AddData([]byte{0x00, 0x00, 0x00, 0x00, 0x00}).Script() + if _, ok := err.(btcscript.ErrScriptNotCanonical); !ok || err == nil { + t.Fatalf("ScriptBuilder.AddData allowed exceeding max script "+ + "size: %v", len(script)) + } + if !bytes.Equal(script, origScript) { + t.Fatalf("ScriptBuilder.AddData unexpected modified script - "+ + "got len %d, want len %d", len(script), len(origScript)) + } + + // Ensure adding data, even using the non-canonical path, to a script + // that has errored doesn't succeed. + script, err = builder.AddFullData([]byte{0x00}).Script() + if _, ok := err.(btcscript.ErrScriptNotCanonical); !ok || err == nil { + t.Fatal("ScriptBuilder.AddFullData succeeded on errored script") + } + if !bytes.Equal(script, origScript) { + t.Fatalf("ScriptBuilder.AddFullData unexpected modified "+ + "script - got len %d, want len %d", len(script), + len(origScript)) + } + + // Ensure adding data to a script that has errored doesn't succeed. + script, err = builder.AddData([]byte{0x00}).Script() + if _, ok := err.(btcscript.ErrScriptNotCanonical); !ok || err == nil { + t.Fatal("ScriptBuilder.AddData succeeded on errored script") + } + if !bytes.Equal(script, origScript) { + t.Fatalf("ScriptBuilder.AddData unexpected modified "+ + "script - got len %d, want len %d", len(script), + len(origScript)) + } + + // Ensure adding an opcode to a script that has errored doesn't succeed. + script, err = builder.AddOp(btcscript.OP_0).Script() + if _, ok := err.(btcscript.ErrScriptNotCanonical); !ok || err == nil { + t.Fatal("ScriptBuilder.AddOp succeeded on errored script") + } + if !bytes.Equal(script, origScript) { + t.Fatalf("ScriptBuilder.AddOp unexpected modified script - "+ + "got len %d, want len %d", len(script), len(origScript)) + } + + // Ensure adding an integer to a script that has errored doesn't + // succeed. + script, err = builder.AddInt64(0).Script() + if _, ok := err.(btcscript.ErrScriptNotCanonical); !ok || err == nil { + t.Fatal("ScriptBuilder.AddInt64 succeeded on errored script") + } + if !bytes.Equal(script, origScript) { + t.Fatalf("ScriptBuilder.AddInt64 unexpected modified script - "+ + "got len %d, want len %d", len(script), len(origScript)) + } + + // Ensure adding an unsigned integer to a script that has errored + // doesn't succeed. + script, err = builder.AddUint64(0).Script() + if _, ok := err.(btcscript.ErrScriptNotCanonical); !ok || err == nil { + t.Fatal("ScriptBuilder.AddUint64 succeeded on errored script") + } + if !bytes.Equal(script, origScript) { + t.Fatalf("ScriptBuilder.AddUint64 unexpected modified script - "+ + "got len %d, want len %d", len(script), len(origScript)) + } + + // Ensure the error has a message set. + if err.Error() == "" { + t.Fatal("ErrScriptNotCanonical.Error does not have any text") + } +} From f513518b4f1f22432999d45598d1d26a76ced12d Mon Sep 17 00:00:00 2001 From: David Hill Date: Tue, 23 Dec 2014 12:15:41 -0500 Subject: [PATCH 170/174] Discourage NOPs reserved for soft-fork upgrades NOP1 through NOP10 are reserved for future soft-fork upgrades. When such an upgrade occurs, the NOP argument will then require verification. Rejecting transactions that contain these NOPs into the mempool will discourage those transactions from being mined elsewhere and ensure btcd will never mine such transactions. This prevents now invalid scripts (according to the majority of hashing power) even if the client has not yet upgraded. Non-executed upgradable NOPs are still allowed as they will still be valid post-upgrade. Mimics Bitcoin Core commit 03914234b3c9c35d66b51d580fe727a0707394ca --- data/script_invalid.json | 16 ++ data/script_valid.json | 4 + internal_test.go | 18 +- opcode.go | 8 +- script.go | 40 +++-- test_coverage.txt | 364 ++++++++++++++++++++------------------- 6 files changed, 251 insertions(+), 199 deletions(-) diff --git a/data/script_invalid.json b/data/script_invalid.json index 75de4716..3574b9d1 100644 --- a/data/script_invalid.json +++ b/data/script_invalid.json @@ -154,6 +154,22 @@ ["1","NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC"], ["'NOP_1_to_10' NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC"], +["Ensure 100% coverage of discouraged NOPS"], +["1", "NOP1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP2", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP3", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP4", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP5", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP6", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP7", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP8", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP9", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP10", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"], + +["NOP10", "1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in scriptSig"], + +["1 0x01 0xb9", "HASH160 0x14 0x15727299b05b45fdaf9ac9ecf7565cfe27c3e567 EQUAL", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in redeemScript"], + ["0x50","1", "P2SH,STRICTENC", "opcode 0x50 is reserved"], ["1", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "opcodes above NOP10 invalid if executed"], ["1", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC"], diff --git a/data/script_valid.json b/data/script_valid.json index c1db4c60..473bd37b 100644 --- a/data/script_valid.json +++ b/data/script_valid.json @@ -226,6 +226,10 @@ ["1","NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 1 EQUAL", "P2SH,STRICTENC"], ["'NOP_1_to_10' NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' EQUAL", "P2SH,STRICTENC"], +["1", "NOP", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", "Discourage NOPx flag allows OP_NOP"], + +["0", "IF NOP10 ENDIF 1", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOPs are allowed if not executed"], + ["0", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "opcodes above NOP10 invalid if executed"], ["0", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC"], ["0", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC"], diff --git a/internal_test.go b/internal_test.go index 5886bb8d..4f74e1f1 100644 --- a/internal_test.go +++ b/internal_test.go @@ -3806,15 +3806,19 @@ func TestBitcoindInvalidTests(t *testing.T) { var tests [][]string err = json.Unmarshal(file, &tests) if err != nil { - t.Errorf("TestBitcoindInvalidTests couldn't Unmarshal: %v\n", + t.Errorf("TestBitcoindInvalidTests couldn't Unmarshal: %v", err) return } tx := btcwire.NewMsgTx() for x, test := range tests { + // Skip comments + if len(test) == 1 { + continue + } name, err := testName(test) if err != nil { - t.Errorf("TestBitcoindInvalidTests: invalid test #%d\n", + t.Errorf("TestBitcoindInvalidTests: invalid test #%d", x) continue } @@ -3857,15 +3861,19 @@ func TestBitcoindValidTests(t *testing.T) { var tests [][]string err = json.Unmarshal(file, &tests) if err != nil { - t.Errorf("TestBitcoindValidTests couldn't Unmarshal: %v\n", + t.Errorf("TestBitcoindValidTests couldn't Unmarshal: %v", err) return } tx := btcwire.NewMsgTx() for x, test := range tests { + // Skip comments + if len(test) == 1 { + continue + } name, err := testName(test) if err != nil { - t.Errorf("TestBitcoindValidTests: invalid test #%d\n", + t.Errorf("TestBitcoindValidTests: invalid test #%d", x) continue } @@ -4195,6 +4203,8 @@ func parseScriptFlags(flagStr string) (ScriptFlags, error) { sFlags := strings.Split(flagStr, ",") for _, flag := range sFlags { switch flag { + case "DISCOURAGE_UPGRADABLE_NOPS": + flags |= ScriptDiscourageUpgradableNops case "NONE": // Nothing. case "NULLDUMMY": diff --git a/opcode.go b/opcode.go index ca4fa8ff..07d6b30f 100644 --- a/opcode.go +++ b/opcode.go @@ -1085,7 +1085,13 @@ func opcodeN(op *parsedOpcode, s *Script) error { } func opcodeNop(op *parsedOpcode, s *Script) error { - // This page left intentionally blank + switch op.opcode.value { + case OP_NOP1, OP_NOP2, OP_NOP3, OP_NOP4, OP_NOP5, + OP_NOP6, OP_NOP7, OP_NOP8, OP_NOP9, OP_NOP10: + if s.discourageUpgradableNops { + return fmt.Errorf("%s reserved for soft-fork upgrades", opcodemap[op.opcode.value].name) + } + } return nil } diff --git a/script.go b/script.go index e6be9339..0a719e69 100644 --- a/script.go +++ b/script.go @@ -195,20 +195,21 @@ func (t ScriptClass) String() string { // Script is the virtual machine that executes btcscripts. type Script struct { - scripts [][]parsedOpcode - scriptidx int - scriptoff int - lastcodesep int - dstack Stack // data stack - astack Stack // alt stack - tx btcwire.MsgTx - txidx int - condStack []int - numOps int - bip16 bool // treat execution as pay-to-script-hash - der bool // enforce DER encoding - strictMultiSig bool // verify multisig stack item is zero length - savedFirstStack [][]byte // stack from first script for bip16 scripts + scripts [][]parsedOpcode + scriptidx int + scriptoff int + lastcodesep int + dstack Stack // data stack + astack Stack // alt stack + tx btcwire.MsgTx + txidx int + condStack []int + numOps int + bip16 bool // treat execution as pay-to-script-hash + der bool // enforce DER encoding + strictMultiSig bool // verify multisig stack item is zero length + discourageUpgradableNops bool // NOP1 to NOP10 are reserved for future soft-fork upgrades + savedFirstStack [][]byte // stack from first script for bip16 scripts } // isSmallInt returns whether or not the opcode is considered a small integer, @@ -513,6 +514,14 @@ const ( // ScriptStrictMultiSig defines whether to verify the stack item // used by CHECKMULTISIG is zero length. ScriptStrictMultiSig + + // ScriptDiscourageUpgradableNops defines whether to verify that + // NOP1 through NOP10 are reserved for future soft-fork upgrades. This + // flag must not be used for consensus critical code nor applied to + // blocks as this flag is only for stricter standard transaction + // checks. This flag is only applied when the above opcodes are + // executed. + ScriptDiscourageUpgradableNops ) // NewScript returns a new script engine for the provided tx and input idx with @@ -558,6 +567,9 @@ func NewScript(scriptSig []byte, scriptPubKey []byte, txidx int, tx *btcwire.Msg if flags&ScriptStrictMultiSig == ScriptStrictMultiSig { m.strictMultiSig = true } + if flags&ScriptDiscourageUpgradableNops == ScriptDiscourageUpgradableNops { + m.discourageUpgradableNops = true + } m.tx = *tx m.txidx = txidx diff --git a/test_coverage.txt b/test_coverage.txt index 61d9a98b..cc8ff18e 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -1,182 +1,186 @@ -github.com/conformal/btcscript/script.go calcScriptHash 100.00% (39/39) -github.com/conformal/btcscript/script.go Script.Step 100.00% (37/37) -github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (29/29) -github.com/conformal/btcscript/opcode.go opcodeCheckSig 100.00% (29/29) -github.com/conformal/btcscript/address.go ExtractPkScriptAddrs 100.00% (27/27) -github.com/conformal/btcscript/script.go NewScript 100.00% (25/25) -github.com/conformal/btcscript/script.go CalcScriptInfo 100.00% (25/25) -github.com/conformal/btcscript/stack.go asInt 100.00% (23/23) -github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddData 100.00% (22/22) -github.com/conformal/btcscript/opcode.go parsedOpcode.disabled 100.00% (17/17) -github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (16/16) -github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (15/15) -github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) -github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (13/13) -github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) -github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) -github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13) -github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) -github.com/conformal/btcscript/script.go PayToAddrScript 100.00% (11/11) -github.com/conformal/btcscript/script.go typeOfScript 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) -github.com/conformal/btcscript/log.go SetLogWriter 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) -github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) -github.com/conformal/btcscript/script.go PushedData 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) -github.com/conformal/btcscript/script.go SignatureScript 100.00% (9/9) -github.com/conformal/btcscript/script.go Script.CheckErrorCondition 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) -github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) -github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) -github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) -github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) -github.com/conformal/btcscript/script.go MultiSigScript 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) -github.com/conformal/btcscript/script.go CalcMultiSigStats 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) -github.com/conformal/btcscript/script.go Script.Execute 100.00% (8/8) -github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) -github.com/conformal/btcscript/script.go HasCanonicalPushes 100.00% (7/7) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddUint64 100.00% (7/7) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddInt64 100.00% (7/7) -github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) -github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodePick 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 100.00% (4/4) -github.com/conformal/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) -github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4) -github.com/conformal/btcscript/script.go isNullData 100.00% (4/4) -github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) -github.com/conformal/btcscript/script.go IsPushOnlyScript 100.00% (4/4) -github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) -github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) -github.com/conformal/btcscript/script.go getStack 100.00% (4/4) -github.com/conformal/btcscript/opcode.go parsedOpcode.alwaysIllegal 100.00% (4/4) -github.com/conformal/btcscript/script.go @1322:17 100.00% (4/4) -github.com/conformal/btcscript/stack.go asBool 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PopBool 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) -github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) -github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) -github.com/conformal/btcscript/script.go ScriptClass.String 100.00% (3/3) -github.com/conformal/btcscript/script.go isSmallInt 100.00% (3/3) -github.com/conformal/btcscript/script.go setStack 100.00% (3/3) -github.com/conformal/btcscript/script.go asSmallInt 100.00% (3/3) -github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) -github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.AddOp 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Reset 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) -github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2) -github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) -github.com/conformal/btcscript/script.go KeyClosure.GetKey 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) -github.com/conformal/btcscript/script.go payToPubKeyHashScript 100.00% (1/1) -github.com/conformal/btcscript/script.go payToScriptHashScript 100.00% (1/1) -github.com/conformal/btcscript/script.go payToPubKeyScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go init 100.00% (1/1) -github.com/conformal/btcscript/scriptbuilder.go NewScriptBuilder 100.00% (1/1) -github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) -github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) -github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) -github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) -github.com/conformal/btcscript/script.go ScriptClosure.GetScript 100.00% (1/1) -github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/conformal/btcscript/log.go init 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1) -github.com/conformal/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.48% (65/66) -github.com/conformal/btcscript/script.go mergeScripts 95.00% (19/20) -github.com/conformal/btcscript/script.go canonicalPush 92.86% (13/14) -github.com/conformal/btcscript/script.go signMultiSig 92.86% (13/14) -github.com/conformal/btcscript/script.go mergeMultiSig 88.10% (37/42) -github.com/conformal/btcscript/script.go signTxOutput 87.50% (7/8) -github.com/conformal/btcscript/script.go unparseScript 85.71% (6/7) -github.com/conformal/btcscript/script.go expectedInputs 85.71% (6/7) -github.com/conformal/btcscript/script.go SignTxOutput 80.00% (12/15) -github.com/conformal/btcscript/script.go p2pkSignatureScript 75.00% (3/4) -github.com/conformal/btcscript/script.go sign 69.23% (18/26) -github.com/conformal/btcscript/script.go @586:34 0.00% (0/6) -github.com/conformal/btcscript/stack.go Stack.String 0.00% (0/4) -github.com/conformal/btcscript/script.go @574:34 0.00% (0/4) -github.com/conformal/btcscript/script.go @619:34 0.00% (0/3) -github.com/conformal/btcscript/opcode.go opcodeDisabled 0.00% (0/1) -github.com/conformal/btcscript/opcode.go @1804:33 0.00% (0/1) -github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 96.52% (1221/1265) +github.com/btcsuite/btcscript/script.go calcScriptHash 100.00% (39/39) +github.com/btcsuite/btcscript/script.go Script.Step 100.00% (37/37) +github.com/btcsuite/btcscript/script.go parseScriptTemplate 100.00% (29/29) +github.com/btcsuite/btcscript/opcode.go opcodeCheckSig 100.00% (29/29) +github.com/btcsuite/btcscript/script.go NewScript 100.00% (27/27) +github.com/btcsuite/btcscript/address.go ExtractPkScriptAddrs 100.00% (27/27) +github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.addData 100.00% (25/25) +github.com/btcsuite/btcscript/script.go CalcScriptInfo 100.00% (25/25) +github.com/btcsuite/btcscript/stack.go asInt 100.00% (23/23) +github.com/btcsuite/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23) +github.com/btcsuite/btcscript/opcode.go parsedOpcode.disabled 100.00% (17/17) +github.com/btcsuite/btcscript/opcode.go parsedOpcode.print 100.00% (16/16) +github.com/btcsuite/btcscript/stack.go Stack.nipN 100.00% (15/15) +github.com/btcsuite/btcscript/scriptbuilder.go canonicalDataSize 100.00% (14/14) +github.com/btcsuite/btcscript/stack.go fromInt 100.00% (14/14) +github.com/btcsuite/btcscript/opcode.go opcodeWithin 100.00% (13/13) +github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.AddUint64 100.00% (13/13) +github.com/btcsuite/btcscript/opcode.go parsedOpcode.exec 100.00% (13/13) +github.com/btcsuite/btcscript/script.go isMultiSig 100.00% (13/13) +github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.AddInt64 100.00% (13/13) +github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.AddData 100.00% (13/13) +github.com/btcsuite/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) +github.com/btcsuite/btcscript/opcode.go opcodeNotIf 100.00% (11/11) +github.com/btcsuite/btcscript/script.go typeOfScript 100.00% (11/11) +github.com/btcsuite/btcscript/opcode.go opcodeIf 100.00% (11/11) +github.com/btcsuite/btcscript/script.go PayToAddrScript 100.00% (11/11) +github.com/btcsuite/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) +github.com/btcsuite/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) +github.com/btcsuite/btcscript/script.go PushedData 100.00% (10/10) +github.com/btcsuite/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) +github.com/btcsuite/btcscript/opcode.go opcodeMin 100.00% (10/10) +github.com/btcsuite/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) +github.com/btcsuite/btcscript/stack.go Stack.Tuck 100.00% (10/10) +github.com/btcsuite/btcscript/script.go getSigOpCount 100.00% (10/10) +github.com/btcsuite/btcscript/log.go SetLogWriter 100.00% (10/10) +github.com/btcsuite/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) +github.com/btcsuite/btcscript/opcode.go opcodeMax 100.00% (10/10) +github.com/btcsuite/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) +github.com/btcsuite/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) +github.com/btcsuite/btcscript/opcode.go opcodeLessThan 100.00% (10/10) +github.com/btcsuite/btcscript/script.go DisasmString 100.00% (9/9) +github.com/btcsuite/btcscript/stack.go Stack.OverN 100.00% (9/9) +github.com/btcsuite/btcscript/stack.go Stack.SwapN 100.00% (9/9) +github.com/btcsuite/btcscript/script.go SignatureScript 100.00% (9/9) +github.com/btcsuite/btcscript/stack.go Stack.RotN 100.00% (9/9) +github.com/btcsuite/btcscript/script.go Script.CheckErrorCondition 100.00% (9/9) +github.com/btcsuite/btcscript/script.go Script.Execute 100.00% (8/8) +github.com/btcsuite/btcscript/opcode.go opcodeEqual 100.00% (8/8) +github.com/btcsuite/btcscript/script.go MultiSigScript 100.00% (8/8) +github.com/btcsuite/btcscript/script.go CalcMultiSigStats 100.00% (8/8) +github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.AddOp 100.00% (8/8) +github.com/btcsuite/btcscript/opcode.go opcodeAdd 100.00% (8/8) +github.com/btcsuite/btcscript/opcode.go opcodeSub 100.00% (8/8) +github.com/btcsuite/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/btcsuite/btcscript/opcode.go opcodeNot 100.00% (7/7) +github.com/btcsuite/btcscript/stack.go Stack.DropN 100.00% (7/7) +github.com/btcsuite/btcscript/opcode.go opcodeNop 100.00% (7/7) +github.com/btcsuite/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) +github.com/btcsuite/btcscript/script.go HasCanonicalPushes 100.00% (7/7) +github.com/btcsuite/btcscript/opcode.go opcodeElse 100.00% (6/6) +github.com/btcsuite/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) +github.com/btcsuite/btcscript/opcode.go opcodeIfDup 100.00% (6/6) +github.com/btcsuite/btcscript/opcode.go opcodeVerify 100.00% (6/6) +github.com/btcsuite/btcscript/opcode.go opcodeEndif 100.00% (6/6) +github.com/btcsuite/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/btcsuite/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) +github.com/btcsuite/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/btcsuite/btcscript/opcode.go opcodePick 100.00% (5/5) +github.com/btcsuite/btcscript/opcode.go opcodeRoll 100.00% (5/5) +github.com/btcsuite/btcscript/opcode.go opcodeSize 100.00% (5/5) +github.com/btcsuite/btcscript/opcode.go opcode1Add 100.00% (5/5) +github.com/btcsuite/btcscript/opcode.go opcode1Sub 100.00% (5/5) +github.com/btcsuite/btcscript/opcode.go opcodeNegate 100.00% (5/5) +github.com/btcsuite/btcscript/opcode.go opcodeAbs 100.00% (5/5) +github.com/btcsuite/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) +github.com/btcsuite/btcscript/opcode.go opcodeSha1 100.00% (5/5) +github.com/btcsuite/btcscript/opcode.go opcodeSha256 100.00% (5/5) +github.com/btcsuite/btcscript/opcode.go opcodeHash160 100.00% (5/5) +github.com/btcsuite/btcscript/opcode.go opcodeHash256 100.00% (5/5) +github.com/btcsuite/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/btcsuite/btcscript/script.go Script.DisasmScript 100.00% (5/5) +github.com/btcsuite/btcscript/script.go removeOpcodeByData 100.00% (5/5) +github.com/btcsuite/btcscript/stack.go Stack.PickN 100.00% (5/5) +github.com/btcsuite/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/btcsuite/btcscript/script.go Script.curPC 100.00% (4/4) +github.com/btcsuite/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) +github.com/btcsuite/btcscript/opcode.go opcodeCheckSigVerify 100.00% (4/4) +github.com/btcsuite/btcscript/opcode.go parsedOpcode.alwaysIllegal 100.00% (4/4) +github.com/btcsuite/btcscript/script.go IsPayToScriptHash 100.00% (4/4) +github.com/btcsuite/btcscript/stack.go Stack.PeekBool 100.00% (4/4) +github.com/btcsuite/btcscript/script.go isNullData 100.00% (4/4) +github.com/btcsuite/btcscript/stack.go Stack.PeekInt 100.00% (4/4) +github.com/btcsuite/btcscript/script.go IsPushOnlyScript 100.00% (4/4) +github.com/btcsuite/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) +github.com/btcsuite/btcscript/stack.go Stack.PopBool 100.00% (4/4) +github.com/btcsuite/btcscript/script.go GetScriptClass 100.00% (4/4) +github.com/btcsuite/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) +github.com/btcsuite/btcscript/stack.go Stack.PopInt 100.00% (4/4) +github.com/btcsuite/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) +github.com/btcsuite/btcscript/stack.go asBool 100.00% (4/4) +github.com/btcsuite/btcscript/script.go getStack 100.00% (4/4) +github.com/btcsuite/btcscript/script.go @1338:17 100.00% (4/4) +github.com/btcsuite/btcscript/script.go isPushOnly 100.00% (4/4) +github.com/btcsuite/btcscript/script.go Script.DisasmPC 100.00% (4/4) +github.com/btcsuite/btcscript/script.go ScriptClass.String 100.00% (3/3) +github.com/btcsuite/btcscript/script.go setStack 100.00% (3/3) +github.com/btcsuite/btcscript/script.go isSmallInt 100.00% (3/3) +github.com/btcsuite/btcscript/script.go asSmallInt 100.00% (3/3) +github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.AddFullData 100.00% (3/3) +github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.Reset 100.00% (3/3) +github.com/btcsuite/btcscript/stack.go fromBool 100.00% (3/3) +github.com/btcsuite/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/btcsuite/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/btcsuite/btcscript/opcode.go calcHash 100.00% (2/2) +github.com/btcsuite/btcscript/opcode.go opcodeFalse 100.00% (2/2) +github.com/btcsuite/btcscript/opcode.go opcodePushData 100.00% (2/2) +github.com/btcsuite/btcscript/opcode.go opcode1Negate 100.00% (2/2) +github.com/btcsuite/btcscript/script.go GetSigOpCount 100.00% (2/2) +github.com/btcsuite/btcscript/stack.go Stack.Depth 100.00% (2/2) +github.com/btcsuite/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/btcsuite/btcscript/opcode.go opcodeN 100.00% (2/2) +github.com/btcsuite/btcscript/script.go Script.SetAltStack 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcodeDrop 100.00% (1/1) +github.com/btcsuite/btcscript/script.go payToPubKeyHashScript 100.00% (1/1) +github.com/btcsuite/btcscript/script.go payToScriptHashScript 100.00% (1/1) +github.com/btcsuite/btcscript/script.go payToPubKeyScript 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcode2Swap 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcode2Rot 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/btcsuite/btcscript/scriptbuilder.go ErrScriptNotCanonical.Error 100.00% (1/1) +github.com/btcsuite/btcscript/script.go KeyClosure.GetKey 100.00% (1/1) +github.com/btcsuite/btcscript/script.go ScriptClosure.GetScript 100.00% (1/1) +github.com/btcsuite/btcscript/script.go Script.disasm 100.00% (1/1) +github.com/btcsuite/btcscript/script.go Script.subScript 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcodeSwap 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcodeNip 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcodeDup 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcodeTuck 100.00% (1/1) +github.com/btcsuite/btcscript/log.go UseLogger 100.00% (1/1) +github.com/btcsuite/btcscript/script.go Script.GetStack 100.00% (1/1) +github.com/btcsuite/btcscript/script.go Script.SetStack 100.00% (1/1) +github.com/btcsuite/btcscript/script.go Script.GetAltStack 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcodeInvalid 100.00% (1/1) +github.com/btcsuite/btcscript/script.go isPubkey 100.00% (1/1) +github.com/btcsuite/btcscript/scriptbuilder.go NewScriptBuilder 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcode2Dup 100.00% (1/1) +github.com/btcsuite/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) +github.com/btcsuite/btcscript/stack.go Stack.PushInt 100.00% (1/1) +github.com/btcsuite/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) +github.com/btcsuite/btcscript/script.go parseScript 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/btcsuite/btcscript/script.go isScriptHash 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go init 100.00% (1/1) +github.com/btcsuite/btcscript/log.go newLogClosure 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcodeOver 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcodeRot 100.00% (1/1) +github.com/btcsuite/btcscript/log.go DisableLog 100.00% (1/1) +github.com/btcsuite/btcscript/log.go init 100.00% (1/1) +github.com/btcsuite/btcscript/stack.go Stack.PushBool 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcode3Dup 100.00% (1/1) +github.com/btcsuite/btcscript/script.go isPubkeyHash 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcode2Drop 100.00% (1/1) +github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcodeReturn 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcodeCheckMultiSig 98.48% (65/66) +github.com/btcsuite/btcscript/script.go mergeScripts 95.24% (20/21) +github.com/btcsuite/btcscript/script.go signMultiSig 93.33% (14/15) +github.com/btcsuite/btcscript/script.go canonicalPush 92.86% (13/14) +github.com/btcsuite/btcscript/script.go mergeMultiSig 88.37% (38/43) +github.com/btcsuite/btcscript/script.go RawTxInSignature 87.50% (7/8) +github.com/btcsuite/btcscript/script.go expectedInputs 85.71% (6/7) +github.com/btcsuite/btcscript/script.go unparseScript 85.71% (6/7) +github.com/btcsuite/btcscript/script.go SignTxOutput 80.00% (12/15) +github.com/btcsuite/btcscript/script.go p2pkSignatureScript 75.00% (3/4) +github.com/btcsuite/btcscript/script.go sign 69.23% (18/26) +github.com/btcsuite/btcscript/script.go @598:34 0.00% (0/6) +github.com/btcsuite/btcscript/script.go @586:34 0.00% (0/4) +github.com/btcsuite/btcscript/stack.go Stack.String 0.00% (0/4) +github.com/btcsuite/btcscript/script.go @631:34 0.00% (0/3) +github.com/btcsuite/btcscript/log.go logClosure.String 0.00% (0/1) +github.com/btcsuite/btcscript/opcode.go @1815:33 0.00% (0/1) +github.com/btcsuite/btcscript/opcode.go opcodeDisabled 0.00% (0/1) +github.com/btcsuite/btcscript --------------------------- 96.69% (1285/1329) From 8e6abdb1257ccef62e5d05e4bcd64f51f8745082 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 29 Jan 2015 14:39:44 -0600 Subject: [PATCH 171/174] Make several of the reg tests more consistent. This commit modifies various regression tests to make them more consistent with other tests throughout the code base. Also, it allows of all the tests to run in parallel. --- opcode_test.go | 970 ++++++++++++------------ script_test.go | 124 +-- stack_test.go | 1972 ++++++++++++++++++++++++------------------------ 3 files changed, 1556 insertions(+), 1510 deletions(-) diff --git a/opcode_test.go b/opcode_test.go index 0de1b7dd..9b4ac4d8 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -12,475 +12,475 @@ import ( "github.com/btcsuite/btcwire" ) -// test scripts to test as many opcodes as possible. -// All run on a fake tx with a single in, single out. -type opcodeTest struct { - script []byte - canonical bool - shouldPass bool - shouldFail error -} +// TestScripts tests script execution for a wide variety of opcodes. All tests +// against a fake transaction with a single input and output. +func TestScripts(t *testing.T) { + t.Parallel() -var opcodeTests = []opcodeTest{ - // does nothing, but doesn't put a true on the stack, should fail - {script: []byte{btcscript.OP_NOP}, shouldPass: false}, - // should just put true on the stack, thus passes. - {script: []byte{btcscript.OP_TRUE}, shouldPass: true}, - // should just put false on the stack, thus fails. - {script: []byte{btcscript.OP_FALSE}, shouldPass: false}, - // tests OP_VERIFY (true). true is needed since else stack is empty. - {script: []byte{btcscript.OP_TRUE, btcscript.OP_VERIFY, - btcscript.OP_TRUE}, shouldPass: true}, - // tests OP_VERIFY (false), will error out. - {script: []byte{btcscript.OP_FALSE, btcscript.OP_VERIFY, - btcscript.OP_TRUE}, shouldPass: false}, - // tests OP_VERIFY with empty stack (errors) - {script: []byte{btcscript.OP_VERIFY}, shouldPass: false}, - // test OP_RETURN immediately fails the script (empty stack) - {script: []byte{btcscript.OP_RETURN}, shouldPass: false}, - // test OP_RETURN immediately fails the script (full stack) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_RETURN}, - shouldPass: false}, - // tests numequal with a trivial example (passing) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_NUMEQUAL}, shouldPass: true}, - // tests numequal with a trivial example (failing) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_NUMEQUAL}, shouldPass: false}, - // tests numequal with insufficient arguments (1/2) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_NUMEQUAL}, - shouldPass: false}, - // tests numequal with insufficient arguments (0/2) - {script: []byte{btcscript.OP_NUMEQUAL}, shouldPass: false}, - // tests numnotequal with a trivial example (passing) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_NUMNOTEQUAL}, shouldPass: true}, - // tests numnotequal with a trivial example (failing) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_NUMNOTEQUAL}, shouldPass: false}, - // tests numnotequal with insufficient arguments (1/2) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_NUMNOTEQUAL}, - shouldPass: false}, - // tests numnotequal with insufficient arguments (0/2) - {script: []byte{btcscript.OP_NUMNOTEQUAL}, shouldPass: false}, - // test numequal_verify with a trivial example (passing) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_NUMEQUALVERIFY, btcscript.OP_TRUE}, - shouldPass: true}, - // test numequal_verify with a trivial example (failing) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_NUMEQUALVERIFY, btcscript.OP_TRUE}, - shouldPass: false}, - // test OP_1ADD by adding 1 to 0 - {script: []byte{btcscript.OP_FALSE, btcscript.OP_1ADD}, - shouldPass: true}, - // test OP_1ADD without args (should error) - {script: []byte{btcscript.OP_1ADD}, shouldPass: false}, - // test OP_1NEGATE by adding 1 to -1 - {script: []byte{btcscript.OP_1NEGATE, btcscript.OP_1ADD}, - shouldPass: false}, - // test OP_1NEGATE by adding negating -1 - {script: []byte{btcscript.OP_1NEGATE, btcscript.OP_NEGATE}, - shouldPass: true}, - // test OP_NEGATE by adding 1 to -1 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_NEGATE, - btcscript.OP_1ADD}, shouldPass: false}, - // test OP_NEGATE with no args - {script: []byte{btcscript.OP_NEGATE}, shouldPass: false}, - // test OP_1SUB -> 1 - 1 = 0 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_1SUB}, - shouldPass: false}, - // test OP_1SUB -> negate(0 -1) = 1 - {script: []byte{btcscript.OP_FALSE, btcscript.OP_1SUB, - btcscript.OP_NEGATE}, shouldPass: true}, - // test OP_1SUB with empty stack - {script: []byte{btcscript.OP_1SUB}, shouldPass: false}, - // OP_DEPTH with empty stack, means 0 on stack at end - {script: []byte{btcscript.OP_DEPTH}, shouldPass: false}, - // 1 +1 -1 = 1. tests depth + add - {script: []byte{btcscript.OP_TRUE, btcscript.OP_DEPTH, btcscript.OP_ADD, - btcscript.OP_1SUB}, shouldPass: true}, - // 1 +1 -1 = 0 . tests dept + add - {script: []byte{btcscript.OP_TRUE, btcscript.OP_DEPTH, - btcscript.OP_ADD, btcscript.OP_1SUB, btcscript.OP_1SUB}, - shouldPass: false}, - // OP_ADD with only one thing on stack should error - {script: []byte{btcscript.OP_TRUE, btcscript.OP_ADD}, - shouldPass: false}, - // OP_ADD with nothing on stack should error - {script: []byte{btcscript.OP_ADD}, shouldPass: false}, - // OP_SUB: 1-1=0 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_SUB}, shouldPass: false}, - // OP_SUB: 1+1-1=1 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_ADD, btcscript.OP_SUB}, shouldPass: true}, - // OP_SUB with only one thing on stack should error - {script: []byte{btcscript.OP_TRUE, btcscript.OP_SUB}, - shouldPass: false}, - // OP_SUB with nothing on stack should error - {script: []byte{btcscript.OP_SUB}, shouldPass: false}, - // OP_LESSTHAN 1 < 1 == false - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_LESSTHAN}, shouldPass: false}, - // OP_LESSTHAN 1 < 0 == false - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_LESSTHAN}, shouldPass: false}, - // OP_LESSTHAN 0 < 1 == true - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, - btcscript.OP_LESSTHAN}, shouldPass: true}, - // OP_LESSTHAN only one arg - {script: []byte{btcscript.OP_TRUE, btcscript.OP_LESSTHAN}, - shouldPass: false}, - // OP_LESSTHAN no args - {script: []byte{btcscript.OP_LESSTHAN}, shouldPass: false}, + tests := []struct { + script []byte + canonical bool + shouldPass bool + shouldFail error + }{ + // does nothing, but doesn't put a true on the stack, should fail + {script: []byte{btcscript.OP_NOP}, shouldPass: false}, + // should just put true on the stack, thus passes. + {script: []byte{btcscript.OP_TRUE}, shouldPass: true}, + // should just put false on the stack, thus fails. + {script: []byte{btcscript.OP_FALSE}, shouldPass: false}, + // tests OP_VERIFY (true). true is needed since else stack is empty. + {script: []byte{btcscript.OP_TRUE, btcscript.OP_VERIFY, + btcscript.OP_TRUE}, shouldPass: true}, + // tests OP_VERIFY (false), will error out. + {script: []byte{btcscript.OP_FALSE, btcscript.OP_VERIFY, + btcscript.OP_TRUE}, shouldPass: false}, + // tests OP_VERIFY with empty stack (errors) + {script: []byte{btcscript.OP_VERIFY}, shouldPass: false}, + // test OP_RETURN immediately fails the script (empty stack) + {script: []byte{btcscript.OP_RETURN}, shouldPass: false}, + // test OP_RETURN immediately fails the script (full stack) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_RETURN}, + shouldPass: false}, + // tests numequal with a trivial example (passing) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_NUMEQUAL}, shouldPass: true}, + // tests numequal with a trivial example (failing) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_NUMEQUAL}, shouldPass: false}, + // tests numequal with insufficient arguments (1/2) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_NUMEQUAL}, + shouldPass: false}, + // tests numequal with insufficient arguments (0/2) + {script: []byte{btcscript.OP_NUMEQUAL}, shouldPass: false}, + // tests numnotequal with a trivial example (passing) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_NUMNOTEQUAL}, shouldPass: true}, + // tests numnotequal with a trivial example (failing) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_NUMNOTEQUAL}, shouldPass: false}, + // tests numnotequal with insufficient arguments (1/2) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_NUMNOTEQUAL}, + shouldPass: false}, + // tests numnotequal with insufficient arguments (0/2) + {script: []byte{btcscript.OP_NUMNOTEQUAL}, shouldPass: false}, + // test numequal_verify with a trivial example (passing) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_NUMEQUALVERIFY, btcscript.OP_TRUE}, + shouldPass: true}, + // test numequal_verify with a trivial example (failing) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_NUMEQUALVERIFY, btcscript.OP_TRUE}, + shouldPass: false}, + // test OP_1ADD by adding 1 to 0 + {script: []byte{btcscript.OP_FALSE, btcscript.OP_1ADD}, + shouldPass: true}, + // test OP_1ADD without args (should error) + {script: []byte{btcscript.OP_1ADD}, shouldPass: false}, + // test OP_1NEGATE by adding 1 to -1 + {script: []byte{btcscript.OP_1NEGATE, btcscript.OP_1ADD}, + shouldPass: false}, + // test OP_1NEGATE by adding negating -1 + {script: []byte{btcscript.OP_1NEGATE, btcscript.OP_NEGATE}, + shouldPass: true}, + // test OP_NEGATE by adding 1 to -1 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_NEGATE, + btcscript.OP_1ADD}, shouldPass: false}, + // test OP_NEGATE with no args + {script: []byte{btcscript.OP_NEGATE}, shouldPass: false}, + // test OP_1SUB -> 1 - 1 = 0 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_1SUB}, + shouldPass: false}, + // test OP_1SUB -> negate(0 -1) = 1 + {script: []byte{btcscript.OP_FALSE, btcscript.OP_1SUB, + btcscript.OP_NEGATE}, shouldPass: true}, + // test OP_1SUB with empty stack + {script: []byte{btcscript.OP_1SUB}, shouldPass: false}, + // OP_DEPTH with empty stack, means 0 on stack at end + {script: []byte{btcscript.OP_DEPTH}, shouldPass: false}, + // 1 +1 -1 = 1. tests depth + add + {script: []byte{btcscript.OP_TRUE, btcscript.OP_DEPTH, btcscript.OP_ADD, + btcscript.OP_1SUB}, shouldPass: true}, + // 1 +1 -1 = 0 . tests dept + add + {script: []byte{btcscript.OP_TRUE, btcscript.OP_DEPTH, + btcscript.OP_ADD, btcscript.OP_1SUB, btcscript.OP_1SUB}, + shouldPass: false}, + // OP_ADD with only one thing on stack should error + {script: []byte{btcscript.OP_TRUE, btcscript.OP_ADD}, + shouldPass: false}, + // OP_ADD with nothing on stack should error + {script: []byte{btcscript.OP_ADD}, shouldPass: false}, + // OP_SUB: 1-1=0 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_SUB}, shouldPass: false}, + // OP_SUB: 1+1-1=1 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_ADD, btcscript.OP_SUB}, shouldPass: true}, + // OP_SUB with only one thing on stack should error + {script: []byte{btcscript.OP_TRUE, btcscript.OP_SUB}, + shouldPass: false}, + // OP_SUB with nothing on stack should error + {script: []byte{btcscript.OP_SUB}, shouldPass: false}, + // OP_LESSTHAN 1 < 1 == false + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_LESSTHAN}, shouldPass: false}, + // OP_LESSTHAN 1 < 0 == false + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_LESSTHAN}, shouldPass: false}, + // OP_LESSTHAN 0 < 1 == true + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, + btcscript.OP_LESSTHAN}, shouldPass: true}, + // OP_LESSTHAN only one arg + {script: []byte{btcscript.OP_TRUE, btcscript.OP_LESSTHAN}, + shouldPass: false}, + // OP_LESSTHAN no args + {script: []byte{btcscript.OP_LESSTHAN}, shouldPass: false}, - // OP_LESSTHANOREQUAL 1 <= 1 == true - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_LESSTHANOREQUAL}, shouldPass: true}, - // OP_LESSTHANOREQUAL 1 <= 0 == false - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_LESSTHANOREQUAL}, shouldPass: false}, - // OP_LESSTHANOREQUAL 0 <= 1 == true - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, - btcscript.OP_LESSTHANOREQUAL}, shouldPass: true}, - // OP_LESSTHANOREQUAL only one arg - {script: []byte{btcscript.OP_TRUE, btcscript.OP_LESSTHANOREQUAL}, - shouldPass: false}, - // OP_LESSTHANOREQUAL no args - {script: []byte{btcscript.OP_LESSTHANOREQUAL}, shouldPass: false}, + // OP_LESSTHANOREQUAL 1 <= 1 == true + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_LESSTHANOREQUAL}, shouldPass: true}, + // OP_LESSTHANOREQUAL 1 <= 0 == false + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_LESSTHANOREQUAL}, shouldPass: false}, + // OP_LESSTHANOREQUAL 0 <= 1 == true + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, + btcscript.OP_LESSTHANOREQUAL}, shouldPass: true}, + // OP_LESSTHANOREQUAL only one arg + {script: []byte{btcscript.OP_TRUE, btcscript.OP_LESSTHANOREQUAL}, + shouldPass: false}, + // OP_LESSTHANOREQUAL no args + {script: []byte{btcscript.OP_LESSTHANOREQUAL}, shouldPass: false}, - // OP_GREATERTHAN 1 > 1 == false - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_GREATERTHAN}, shouldPass: false}, - // OP_GREATERTHAN 1 > 0 == true - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_GREATERTHAN}, shouldPass: true}, - // OP_GREATERTHAN 0 > 1 == false - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, - btcscript.OP_GREATERTHAN}, shouldPass: false}, - // OP_GREATERTHAN only one arg - {script: []byte{btcscript.OP_TRUE, btcscript.OP_GREATERTHAN}, - shouldPass: false}, - // OP_GREATERTHAN no args - {script: []byte{btcscript.OP_GREATERTHAN}, shouldPass: false}, + // OP_GREATERTHAN 1 > 1 == false + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_GREATERTHAN}, shouldPass: false}, + // OP_GREATERTHAN 1 > 0 == true + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_GREATERTHAN}, shouldPass: true}, + // OP_GREATERTHAN 0 > 1 == false + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, + btcscript.OP_GREATERTHAN}, shouldPass: false}, + // OP_GREATERTHAN only one arg + {script: []byte{btcscript.OP_TRUE, btcscript.OP_GREATERTHAN}, + shouldPass: false}, + // OP_GREATERTHAN no args + {script: []byte{btcscript.OP_GREATERTHAN}, shouldPass: false}, - // OP_GREATERTHANOREQUAL 1 >= 1 == true - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_GREATERTHANOREQUAL}, shouldPass: true}, - // OP_GREATERTHANOREQUAL 1 >= 0 == false - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_GREATERTHANOREQUAL}, shouldPass: true}, - // OP_GREATERTHANOREQUAL 0 >= 1 == true - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, - btcscript.OP_GREATERTHANOREQUAL}, shouldPass: false}, - // OP_GREATERTHANOREQUAL only one arg - {script: []byte{btcscript.OP_TRUE, btcscript.OP_GREATERTHANOREQUAL}, - shouldPass: false}, - // OP_GREATERTHANOREQUAL no args - {script: []byte{btcscript.OP_GREATERTHANOREQUAL}, shouldPass: false}, + // OP_GREATERTHANOREQUAL 1 >= 1 == true + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_GREATERTHANOREQUAL}, shouldPass: true}, + // OP_GREATERTHANOREQUAL 1 >= 0 == false + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_GREATERTHANOREQUAL}, shouldPass: true}, + // OP_GREATERTHANOREQUAL 0 >= 1 == true + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, + btcscript.OP_GREATERTHANOREQUAL}, shouldPass: false}, + // OP_GREATERTHANOREQUAL only one arg + {script: []byte{btcscript.OP_TRUE, btcscript.OP_GREATERTHANOREQUAL}, + shouldPass: false}, + // OP_GREATERTHANOREQUAL no args + {script: []byte{btcscript.OP_GREATERTHANOREQUAL}, shouldPass: false}, - // OP_MIN basic functionality -> min(0,1) = 0 = min(1,0) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_MIN}, shouldPass: false}, - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, - btcscript.OP_MIN}, shouldPass: false}, - // OP_MIN -> 1 arg errors - {script: []byte{btcscript.OP_TRUE, btcscript.OP_MIN}, - shouldPass: false}, - // OP_MIN -> 0 arg errors - {script: []byte{btcscript.OP_MIN}, shouldPass: false}, - // OP_MAX basic functionality -> max(0,1) = 1 = max(1,0) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_MAX}, shouldPass: true}, - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, - btcscript.OP_MAX}, shouldPass: true}, - // OP_MAX -> 1 arg errors - {script: []byte{btcscript.OP_TRUE, btcscript.OP_MAX}, - shouldPass: false}, - // OP_MAX -> 0 arg errors - {script: []byte{btcscript.OP_MAX}, shouldPass: false}, + // OP_MIN basic functionality -> min(0,1) = 0 = min(1,0) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_MIN}, shouldPass: false}, + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, + btcscript.OP_MIN}, shouldPass: false}, + // OP_MIN -> 1 arg errors + {script: []byte{btcscript.OP_TRUE, btcscript.OP_MIN}, + shouldPass: false}, + // OP_MIN -> 0 arg errors + {script: []byte{btcscript.OP_MIN}, shouldPass: false}, + // OP_MAX basic functionality -> max(0,1) = 1 = max(1,0) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_MAX}, shouldPass: true}, + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, + btcscript.OP_MAX}, shouldPass: true}, + // OP_MAX -> 1 arg errors + {script: []byte{btcscript.OP_TRUE, btcscript.OP_MAX}, + shouldPass: false}, + // OP_MAX -> 0 arg errors + {script: []byte{btcscript.OP_MAX}, shouldPass: false}, - // By this point we know a number of operations appear to be working - // correctly. we can use them to test the other number pushing - // operations - {script: []byte{btcscript.OP_TRUE, btcscript.OP_1ADD, btcscript.OP_2, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_2, btcscript.OP_1ADD, btcscript.OP_3, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_3, btcscript.OP_1ADD, btcscript.OP_4, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_4, btcscript.OP_1ADD, btcscript.OP_5, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_5, btcscript.OP_1ADD, btcscript.OP_6, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_6, btcscript.OP_1ADD, btcscript.OP_7, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_7, btcscript.OP_1ADD, btcscript.OP_8, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_8, btcscript.OP_1ADD, btcscript.OP_9, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_9, btcscript.OP_1ADD, btcscript.OP_10, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_10, btcscript.OP_1ADD, btcscript.OP_11, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_11, btcscript.OP_1ADD, btcscript.OP_12, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_12, btcscript.OP_1ADD, btcscript.OP_13, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_13, btcscript.OP_1ADD, btcscript.OP_14, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_14, btcscript.OP_1ADD, btcscript.OP_15, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_15, btcscript.OP_1ADD, btcscript.OP_16, - btcscript.OP_EQUAL}, shouldPass: true}, + // By this point we know a number of operations appear to be working + // correctly. we can use them to test the other number pushing + // operations + {script: []byte{btcscript.OP_TRUE, btcscript.OP_1ADD, btcscript.OP_2, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_2, btcscript.OP_1ADD, btcscript.OP_3, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_3, btcscript.OP_1ADD, btcscript.OP_4, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_4, btcscript.OP_1ADD, btcscript.OP_5, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_5, btcscript.OP_1ADD, btcscript.OP_6, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_6, btcscript.OP_1ADD, btcscript.OP_7, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_7, btcscript.OP_1ADD, btcscript.OP_8, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_8, btcscript.OP_1ADD, btcscript.OP_9, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_9, btcscript.OP_1ADD, btcscript.OP_10, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_10, btcscript.OP_1ADD, btcscript.OP_11, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_11, btcscript.OP_1ADD, btcscript.OP_12, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_12, btcscript.OP_1ADD, btcscript.OP_13, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_13, btcscript.OP_1ADD, btcscript.OP_14, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_14, btcscript.OP_1ADD, btcscript.OP_15, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_15, btcscript.OP_1ADD, btcscript.OP_16, + btcscript.OP_EQUAL}, shouldPass: true}, - // Test OP_WITHIN x, min, max - // 0 <= 1 < 2 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, btcscript.OP_2, - btcscript.OP_WITHIN}, shouldPass: true}, - // 1 <= 0 < 2 FAIL - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, btcscript.OP_2, - btcscript.OP_WITHIN}, shouldPass: false}, - // 1 <= 1 < 2 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, btcscript.OP_2, - btcscript.OP_WITHIN}, shouldPass: true}, - // 1 <= 2 < 2 FAIL - {script: []byte{btcscript.OP_2, btcscript.OP_TRUE, btcscript.OP_2, - btcscript.OP_WITHIN}, shouldPass: false}, - // only two arguments - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_WITHIN}, shouldPass: false}, - // only one argument - {script: []byte{btcscript.OP_TRUE, btcscript.OP_WITHIN}, - shouldPass: false}, - // no arguments - {script: []byte{btcscript.OP_WITHIN}, shouldPass: false}, + // Test OP_WITHIN x, min, max + // 0 <= 1 < 2 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, btcscript.OP_2, + btcscript.OP_WITHIN}, shouldPass: true}, + // 1 <= 0 < 2 FAIL + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, btcscript.OP_2, + btcscript.OP_WITHIN}, shouldPass: false}, + // 1 <= 1 < 2 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, btcscript.OP_2, + btcscript.OP_WITHIN}, shouldPass: true}, + // 1 <= 2 < 2 FAIL + {script: []byte{btcscript.OP_2, btcscript.OP_TRUE, btcscript.OP_2, + btcscript.OP_WITHIN}, shouldPass: false}, + // only two arguments + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_WITHIN}, shouldPass: false}, + // only one argument + {script: []byte{btcscript.OP_TRUE, btcscript.OP_WITHIN}, + shouldPass: false}, + // no arguments + {script: []byte{btcscript.OP_WITHIN}, shouldPass: false}, - // OP_BOOLAND - // 1 && 1 == 1 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_BOOLAND}, shouldPass: true}, - // 1 && 0 == 0 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_BOOLAND}, shouldPass: false}, - // 0 && 1 == 0 - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, - btcscript.OP_BOOLAND}, shouldPass: false}, - // 0 && 0 == 0 - {script: []byte{btcscript.OP_FALSE, btcscript.OP_FALSE, - btcscript.OP_BOOLAND}, shouldPass: false}, - // 0 && - boom - {script: []byte{btcscript.OP_TRUE, btcscript.OP_BOOLAND}, - shouldPass: false}, - // && - boom - {script: []byte{btcscript.OP_BOOLAND}, shouldPass: false}, + // OP_BOOLAND + // 1 && 1 == 1 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_BOOLAND}, shouldPass: true}, + // 1 && 0 == 0 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_BOOLAND}, shouldPass: false}, + // 0 && 1 == 0 + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, + btcscript.OP_BOOLAND}, shouldPass: false}, + // 0 && 0 == 0 + {script: []byte{btcscript.OP_FALSE, btcscript.OP_FALSE, + btcscript.OP_BOOLAND}, shouldPass: false}, + // 0 && - boom + {script: []byte{btcscript.OP_TRUE, btcscript.OP_BOOLAND}, + shouldPass: false}, + // && - boom + {script: []byte{btcscript.OP_BOOLAND}, shouldPass: false}, - // OP_BOOLOR - // 1 || 1 == 1 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_BOOLOR}, shouldPass: true}, - // 1 || 0 == 1 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_BOOLOR}, shouldPass: true}, - // 0 || 1 == 1 - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, - btcscript.OP_BOOLOR}, shouldPass: true}, - // 0 || 0 == 0 - {script: []byte{btcscript.OP_FALSE, btcscript.OP_FALSE, - btcscript.OP_BOOLOR}, shouldPass: false}, - // 0 && - boom - {script: []byte{btcscript.OP_TRUE, btcscript.OP_BOOLOR}, - shouldPass: false}, - // && - boom - {script: []byte{btcscript.OP_BOOLOR}, shouldPass: false}, + // OP_BOOLOR + // 1 || 1 == 1 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_BOOLOR}, shouldPass: true}, + // 1 || 0 == 1 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_BOOLOR}, shouldPass: true}, + // 0 || 1 == 1 + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, + btcscript.OP_BOOLOR}, shouldPass: true}, + // 0 || 0 == 0 + {script: []byte{btcscript.OP_FALSE, btcscript.OP_FALSE, + btcscript.OP_BOOLOR}, shouldPass: false}, + // 0 && - boom + {script: []byte{btcscript.OP_TRUE, btcscript.OP_BOOLOR}, + shouldPass: false}, + // && - boom + {script: []byte{btcscript.OP_BOOLOR}, shouldPass: false}, - // OP_0NOTEQUAL - // 1 with input != 0 XXX check output is actually 1. - {script: []byte{btcscript.OP_TRUE, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_2, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_3, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_4, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_5, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_6, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_7, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_8, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_9, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_10, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_11, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_12, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_13, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_14, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_15, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_16, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_FALSE, btcscript.OP_0NOTEQUAL}, shouldPass: false}, - // No arguments also blows up - {script: []byte{btcscript.OP_0NOTEQUAL}, shouldPass: false}, + // OP_0NOTEQUAL + // 1 with input != 0 XXX check output is actually 1. + {script: []byte{btcscript.OP_TRUE, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_2, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_3, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_4, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_5, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_6, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_7, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_8, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_9, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_10, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_11, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_12, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_13, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_14, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_15, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_16, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_FALSE, btcscript.OP_0NOTEQUAL}, shouldPass: false}, + // No arguments also blows up + {script: []byte{btcscript.OP_0NOTEQUAL}, shouldPass: false}, - // OP_NOT: 1 i input is 0, else 0 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_2, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_3, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_4, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_5, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_6, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_7, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_8, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_9, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_10, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_11, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_12, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_13, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_14, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_15, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_16, btcscript.OP_NOT}, shouldPass: false}, - // check negative numbers too - {script: []byte{btcscript.OP_TRUE, btcscript.OP_NEGATE, - btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_FALSE, btcscript.OP_NOT}, - shouldPass: true}, - // No arguments also blows up - {script: []byte{btcscript.OP_NOT}, shouldPass: false}, + // OP_NOT: 1 i input is 0, else 0 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_2, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_3, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_4, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_5, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_6, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_7, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_8, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_9, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_10, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_11, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_12, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_13, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_14, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_15, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_16, btcscript.OP_NOT}, shouldPass: false}, + // check negative numbers too + {script: []byte{btcscript.OP_TRUE, btcscript.OP_NEGATE, + btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_FALSE, btcscript.OP_NOT}, + shouldPass: true}, + // No arguments also blows up + {script: []byte{btcscript.OP_NOT}, shouldPass: false}, - // Conditional Execution - {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: true}, - {script: []byte{btcscript.OP_1, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: false}, - {script: []byte{btcscript.OP_1, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: true}, - {script: []byte{btcscript.OP_0, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: false}, - {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2}, shouldFail: btcscript.ErrStackMissingEndif}, - {script: []byte{btcscript.OP_1, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2}, shouldFail: btcscript.ErrStackMissingEndif}, - {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_IF, btcscript.OP_IF, btcscript.OP_1, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ENDIF}, shouldPass: true}, - {script: []byte{btcscript.OP_1, btcscript.OP_IF, btcscript.OP_IF, btcscript.OP_1, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ENDIF}, shouldFail: btcscript.ErrStackUnderflow}, - {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ELSE, btcscript.OP_1, btcscript.OP_ENDIF}, shouldPass: true}, - {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ELSE, btcscript.OP_1, btcscript.OP_ENDIF}, shouldPass: true}, - {script: []byte{btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ENDIF}, shouldFail: btcscript.ErrStackUnderflow}, - {script: []byte{btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF}, shouldFail: btcscript.ErrStackNoIf}, - {script: []byte{btcscript.OP_ENDIF}, shouldFail: btcscript.ErrStackNoIf}, - /* up here because error from sig parsing is undefined. */ - {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_DATA_65, - 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, - 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, - 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, 0x71, 0x30, 0x2f, - 0xa2, 0x84, 0x14, 0xe7, 0xaa, 0xb3, 0x73, 0x97, 0xf5, 0x54, - 0xa7, 0xdf, 0x5f, 0x14, 0x2c, 0x21, 0xc1, 0xb7, 0x30, 0x3b, - 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, - 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, - btcscript.OP_1, btcscript.OP_CHECKMULTISIG}, - canonical: false, - shouldPass: false}, - {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_DATA_65, - 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, - 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, - 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, 0x71, 0x30, 0x2f, - 0xa2, 0x84, 0x14, 0xe7, 0xaa, 0xb3, 0x73, 0x97, 0xf5, 0x54, - 0xa7, 0xdf, 0x5f, 0x14, 0x2c, 0x21, 0xc1, 0xb7, 0x30, 0x3b, - 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, - 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, - btcscript.OP_1, btcscript.OP_CHECKMULTISIG}, - canonical: true, - shouldPass: false}, - /* up here because no defined error case. */ - {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_DATA_65, - 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, - 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, - 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, 0x71, 0x30, 0x2f, - 0xa2, 0x84, 0x14, 0xe7, 0xaa, 0xb3, 0x73, 0x97, 0xf5, 0x54, - 0xa7, 0xdf, 0x5f, 0x14, 0x2c, 0x21, 0xc1, 0xb7, 0x30, 0x3b, - 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, - 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, - btcscript.OP_1, btcscript.OP_CHECKMULTISIGVERIFY}, - shouldPass: false}, + // Conditional Execution + {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: true}, + {script: []byte{btcscript.OP_1, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: false}, + {script: []byte{btcscript.OP_1, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: true}, + {script: []byte{btcscript.OP_0, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: false}, + {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2}, shouldFail: btcscript.ErrStackMissingEndif}, + {script: []byte{btcscript.OP_1, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2}, shouldFail: btcscript.ErrStackMissingEndif}, + {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_IF, btcscript.OP_IF, btcscript.OP_1, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ENDIF}, shouldPass: true}, + {script: []byte{btcscript.OP_1, btcscript.OP_IF, btcscript.OP_IF, btcscript.OP_1, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ENDIF}, shouldFail: btcscript.ErrStackUnderflow}, + {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ELSE, btcscript.OP_1, btcscript.OP_ENDIF}, shouldPass: true}, + {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ELSE, btcscript.OP_1, btcscript.OP_ENDIF}, shouldPass: true}, + {script: []byte{btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ENDIF}, shouldFail: btcscript.ErrStackUnderflow}, + {script: []byte{btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF}, shouldFail: btcscript.ErrStackNoIf}, + {script: []byte{btcscript.OP_ENDIF}, shouldFail: btcscript.ErrStackNoIf}, + /* up here because error from sig parsing is undefined. */ + {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_DATA_65, + 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, + 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, + 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, 0x71, 0x30, 0x2f, + 0xa2, 0x84, 0x14, 0xe7, 0xaa, 0xb3, 0x73, 0x97, 0xf5, 0x54, + 0xa7, 0xdf, 0x5f, 0x14, 0x2c, 0x21, 0xc1, 0xb7, 0x30, 0x3b, + 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, + 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, + btcscript.OP_1, btcscript.OP_CHECKMULTISIG}, + canonical: false, + shouldPass: false}, + {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_DATA_65, + 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, + 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, + 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, 0x71, 0x30, 0x2f, + 0xa2, 0x84, 0x14, 0xe7, 0xaa, 0xb3, 0x73, 0x97, 0xf5, 0x54, + 0xa7, 0xdf, 0x5f, 0x14, 0x2c, 0x21, 0xc1, 0xb7, 0x30, 0x3b, + 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, + 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, + btcscript.OP_1, btcscript.OP_CHECKMULTISIG}, + canonical: true, + shouldPass: false}, + /* up here because no defined error case. */ + {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_DATA_65, + 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, + 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, + 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, 0x71, 0x30, 0x2f, + 0xa2, 0x84, 0x14, 0xe7, 0xaa, 0xb3, 0x73, 0x97, 0xf5, 0x54, + 0xa7, 0xdf, 0x5f, 0x14, 0x2c, 0x21, 0xc1, 0xb7, 0x30, 0x3b, + 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, + 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, + btcscript.OP_1, btcscript.OP_CHECKMULTISIGVERIFY}, + shouldPass: false}, - // Invalid Opcodes - {script: []byte{186}, shouldPass: false}, - {script: []byte{187}, shouldPass: false}, - {script: []byte{188}, shouldPass: false}, - {script: []byte{189}, shouldPass: false}, - {script: []byte{190}, shouldPass: false}, - {script: []byte{191}, shouldPass: false}, - {script: []byte{192}, shouldPass: false}, - {script: []byte{193}, shouldPass: false}, - {script: []byte{194}, shouldPass: false}, - {script: []byte{195}, shouldPass: false}, - {script: []byte{195}, shouldPass: false}, - {script: []byte{196}, shouldPass: false}, - {script: []byte{197}, shouldPass: false}, - {script: []byte{198}, shouldPass: false}, - {script: []byte{199}, shouldPass: false}, - {script: []byte{200}, shouldPass: false}, - {script: []byte{201}, shouldPass: false}, - {script: []byte{202}, shouldPass: false}, - {script: []byte{203}, shouldPass: false}, - {script: []byte{204}, shouldPass: false}, - {script: []byte{205}, shouldPass: false}, - {script: []byte{206}, shouldPass: false}, - {script: []byte{207}, shouldPass: false}, - {script: []byte{208}, shouldPass: false}, - {script: []byte{209}, shouldPass: false}, - {script: []byte{210}, shouldPass: false}, - {script: []byte{211}, shouldPass: false}, - {script: []byte{212}, shouldPass: false}, - {script: []byte{213}, shouldPass: false}, - {script: []byte{214}, shouldPass: false}, - {script: []byte{215}, shouldPass: false}, - {script: []byte{216}, shouldPass: false}, - {script: []byte{217}, shouldPass: false}, - {script: []byte{218}, shouldPass: false}, - {script: []byte{219}, shouldPass: false}, - {script: []byte{220}, shouldPass: false}, - {script: []byte{221}, shouldPass: false}, - {script: []byte{222}, shouldPass: false}, - {script: []byte{223}, shouldPass: false}, - {script: []byte{224}, shouldPass: false}, - {script: []byte{225}, shouldPass: false}, - {script: []byte{226}, shouldPass: false}, - {script: []byte{227}, shouldPass: false}, - {script: []byte{228}, shouldPass: false}, - {script: []byte{229}, shouldPass: false}, - {script: []byte{230}, shouldPass: false}, - {script: []byte{231}, shouldPass: false}, - {script: []byte{232}, shouldPass: false}, - {script: []byte{233}, shouldPass: false}, - {script: []byte{234}, shouldPass: false}, - {script: []byte{235}, shouldPass: false}, - {script: []byte{236}, shouldPass: false}, - {script: []byte{237}, shouldPass: false}, - {script: []byte{238}, shouldPass: false}, - {script: []byte{239}, shouldPass: false}, - {script: []byte{240}, shouldPass: false}, - {script: []byte{241}, shouldPass: false}, - {script: []byte{242}, shouldPass: false}, - {script: []byte{243}, shouldPass: false}, - {script: []byte{244}, shouldPass: false}, - {script: []byte{245}, shouldPass: false}, - {script: []byte{246}, shouldPass: false}, - {script: []byte{247}, shouldPass: false}, - {script: []byte{248}, shouldPass: false}, - {script: []byte{249}, shouldPass: false}, - {script: []byte{250}, shouldPass: false}, - {script: []byte{251}, shouldPass: false}, - {script: []byte{252}, shouldPass: false}, -} + // Invalid Opcodes + {script: []byte{186}, shouldPass: false}, + {script: []byte{187}, shouldPass: false}, + {script: []byte{188}, shouldPass: false}, + {script: []byte{189}, shouldPass: false}, + {script: []byte{190}, shouldPass: false}, + {script: []byte{191}, shouldPass: false}, + {script: []byte{192}, shouldPass: false}, + {script: []byte{193}, shouldPass: false}, + {script: []byte{194}, shouldPass: false}, + {script: []byte{195}, shouldPass: false}, + {script: []byte{195}, shouldPass: false}, + {script: []byte{196}, shouldPass: false}, + {script: []byte{197}, shouldPass: false}, + {script: []byte{198}, shouldPass: false}, + {script: []byte{199}, shouldPass: false}, + {script: []byte{200}, shouldPass: false}, + {script: []byte{201}, shouldPass: false}, + {script: []byte{202}, shouldPass: false}, + {script: []byte{203}, shouldPass: false}, + {script: []byte{204}, shouldPass: false}, + {script: []byte{205}, shouldPass: false}, + {script: []byte{206}, shouldPass: false}, + {script: []byte{207}, shouldPass: false}, + {script: []byte{208}, shouldPass: false}, + {script: []byte{209}, shouldPass: false}, + {script: []byte{210}, shouldPass: false}, + {script: []byte{211}, shouldPass: false}, + {script: []byte{212}, shouldPass: false}, + {script: []byte{213}, shouldPass: false}, + {script: []byte{214}, shouldPass: false}, + {script: []byte{215}, shouldPass: false}, + {script: []byte{216}, shouldPass: false}, + {script: []byte{217}, shouldPass: false}, + {script: []byte{218}, shouldPass: false}, + {script: []byte{219}, shouldPass: false}, + {script: []byte{220}, shouldPass: false}, + {script: []byte{221}, shouldPass: false}, + {script: []byte{222}, shouldPass: false}, + {script: []byte{223}, shouldPass: false}, + {script: []byte{224}, shouldPass: false}, + {script: []byte{225}, shouldPass: false}, + {script: []byte{226}, shouldPass: false}, + {script: []byte{227}, shouldPass: false}, + {script: []byte{228}, shouldPass: false}, + {script: []byte{229}, shouldPass: false}, + {script: []byte{230}, shouldPass: false}, + {script: []byte{231}, shouldPass: false}, + {script: []byte{232}, shouldPass: false}, + {script: []byte{233}, shouldPass: false}, + {script: []byte{234}, shouldPass: false}, + {script: []byte{235}, shouldPass: false}, + {script: []byte{236}, shouldPass: false}, + {script: []byte{237}, shouldPass: false}, + {script: []byte{238}, shouldPass: false}, + {script: []byte{239}, shouldPass: false}, + {script: []byte{240}, shouldPass: false}, + {script: []byte{241}, shouldPass: false}, + {script: []byte{242}, shouldPass: false}, + {script: []byte{243}, shouldPass: false}, + {script: []byte{244}, shouldPass: false}, + {script: []byte{245}, shouldPass: false}, + {script: []byte{246}, shouldPass: false}, + {script: []byte{247}, shouldPass: false}, + {script: []byte{248}, shouldPass: false}, + {script: []byte{249}, shouldPass: false}, + {script: []byte{250}, shouldPass: false}, + {script: []byte{251}, shouldPass: false}, + {script: []byte{252}, shouldPass: false}, + } -func testScript(t *testing.T, script []byte, canonical bool) (err error) { - // mock up fake tx. - tx := &btcwire.MsgTx{ + // Mock up fake tx used during script execution. + mockTx := &btcwire.MsgTx{ Version: 1, TxIn: []*btcwire.TxIn{ { @@ -501,38 +501,38 @@ func testScript(t *testing.T, script []byte, canonical bool) (err error) { LockTime: 0, } - tx.TxOut[0].PkScript = script + for i, test := range tests { + // Parse and execute the test script. + var flags btcscript.ScriptFlags + if test.canonical { + flags = btcscript.ScriptCanonicalSignatures + } + mockTx.TxOut[0].PkScript = test.script + sigScript := mockTx.TxIn[0].SignatureScript + engine, err := btcscript.NewScript(sigScript, test.script, 0, + mockTx, flags) + if err == nil { + err = engine.Execute() + } - var flags btcscript.ScriptFlags - if canonical { - flags = btcscript.ScriptCanonicalSignatures - } - - engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript, - tx.TxOut[0].PkScript, 0, tx, flags) - if err != nil { - return err - } - return engine.Execute() -} - -func TestScripts(t *testing.T) { - // for each entry in the list - for i := range opcodeTests { - shouldPass := opcodeTests[i].shouldPass - shouldFail := opcodeTests[i].shouldFail - err := testScript(t, opcodeTests[i].script, opcodeTests[i].canonical) - if shouldFail != nil { + if test.shouldFail != nil { if err == nil { - t.Errorf("test %d passed should fail with %v", i, err) - } else if shouldFail != err { - t.Errorf("test %d failed with wrong error [%v], expected [%v]", i, err, shouldFail) + t.Errorf("test %d passed should fail with %v", + i, test.shouldFail) + continue + } else if test.shouldFail != err { + t.Errorf("test %d failed with wrong error "+ + "[%v], expected [%v]", i, err, + test.shouldFail) + continue } } - if shouldPass && err != nil { + if test.shouldPass && err != nil { t.Errorf("test %d failed: %v", i, err) - } else if !shouldPass && err == nil { + continue + } else if !test.shouldPass && err == nil { t.Errorf("test %d passed, should fail", i) + continue } } } @@ -4374,6 +4374,8 @@ func testOpcode(t *testing.T, test *detailedTest) { } func TestOpcodes(t *testing.T) { + t.Parallel() + for i := range detailedTests { testOpcode(t, &detailedTests[i]) } @@ -4402,6 +4404,8 @@ func testDisasmString(t *testing.T, test *detailedTest) { } func TestDisasmStrings(t *testing.T) { + t.Parallel() + for i := range detailedTests { testDisasmString(t, &detailedTests[i]) } @@ -4414,6 +4418,8 @@ func TestDisasmStrings(t *testing.T) { // While this isn't as precise as using full transaction scripts, this gives // us coverage over a wider range of opcodes. func TestSigOps(t *testing.T) { + t.Parallel() + for _, test := range detailedTests { count := btcscript.GetSigOpCount(test.script) if count != test.nSigOps { @@ -4432,6 +4438,8 @@ func TestSigOps(t *testing.T) { // us coverage over a wider range of opcodes. See script_test.go for tests // using real transactions to provide a bit more coverage. func TestPreciseSigOps(t *testing.T) { + t.Parallel() + for _, test := range detailedTests { count := btcscript.GetPreciseSigOpCount( []byte{btcscript.OP_1}, test.script, false) diff --git a/script_test.go b/script_test.go index 8ff919a7..388bd8d2 100644 --- a/script_test.go +++ b/script_test.go @@ -30,6 +30,8 @@ func builderScript(builder *btcscript.ScriptBuilder) []byte { } func TestPushedData(t *testing.T) { + t.Parallel() + var tests = []struct { in []byte out [][]byte @@ -90,6 +92,8 @@ func TestPushedData(t *testing.T) { } func TestStandardPushes(t *testing.T) { + t.Parallel() + for i := 0; i < 65535; i++ { builder := btcscript.NewScriptBuilder() builder.AddInt64(int64(i)) @@ -1652,12 +1656,16 @@ func testTx(t *testing.T, test txTest) { } func TestTX(t *testing.T) { + t.Parallel() + for i := range txTests { testTx(t, txTests[i]) } } func TestGetPreciseSignOps(t *testing.T) { + t.Parallel() + // First we go over the range of tests in testTx and count the sigops in // them. for _, test := range txTests { @@ -1742,6 +1750,8 @@ type scriptInfoTest struct { } func TestScriptInfo(t *testing.T) { + t.Parallel() + for _, test := range txTests { si, err := btcscript.CalcScriptInfo( test.tx.TxIn[test.idx].SignatureScript, @@ -1996,6 +2006,8 @@ func testRemoveOpcode(t *testing.T, test *removeOpcodeTest) { } func TestRemoveOpcodes(t *testing.T) { + t.Parallel() + for i := range removeOpcodeTests { testRemoveOpcode(t, &removeOpcodeTests[i]) } @@ -2134,6 +2146,8 @@ func testRemoveOpcodeByData(t *testing.T, test *removeOpcodeByDataTest) { } } func TestRemoveOpcodeByDatas(t *testing.T) { + t.Parallel() + for i := range removeOpcodeByDataTests { testRemoveOpcodeByData(t, &removeOpcodeByDataTests[i]) } @@ -2361,12 +2375,16 @@ func testScriptType(t *testing.T, test *scriptTypeTest) { } func TestScriptTypes(t *testing.T) { + t.Parallel() + for i := range scriptTypeTests { testScriptType(t, &scriptTypeTests[i]) } } func TestIsPayToScriptHash(t *testing.T) { + t.Parallel() + for _, test := range scriptTypeTests { shouldBe := (test.scripttype == btcscript.ScriptHashTy) p2sh := btcscript.IsPayToScriptHash(test.script) @@ -2380,6 +2398,8 @@ func TestIsPayToScriptHash(t *testing.T) { // This test sets the pc to a deliberately bad result then confirms that Step() // and Disasm fail correctly. func TestBadPC(t *testing.T) { + t.Parallel() + type pcTest struct { script, off int } @@ -2452,6 +2472,8 @@ func TestBadPC(t *testing.T) { // Most codepaths in CheckErrorCondition() are testd elsewhere, this tests // the execute early test. func TestCheckErrorCondition(t *testing.T) { + t.Parallel() + // tx with almost empty scripts. tx := &btcwire.MsgTx{ Version: 1, @@ -2787,6 +2809,8 @@ var SigScriptTests = []TstSigScript{ // created for the MsgTxs in txTests, since they come from the blockchain // and we don't have the private keys. func TestSignatureScript(t *testing.T) { + t.Parallel() + privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), privKeyD) nexttest: @@ -2868,50 +2892,52 @@ nexttest: } } -var classStringifyTests = []struct { - name string - scriptclass btcscript.ScriptClass - stringed string -}{ - { - name: "nonstandardty", - scriptclass: btcscript.NonStandardTy, - stringed: "nonstandard", - }, - { - name: "pubkey", - scriptclass: btcscript.PubKeyTy, - stringed: "pubkey", - }, - { - name: "pubkeyhash", - scriptclass: btcscript.PubKeyHashTy, - stringed: "pubkeyhash", - }, - { - name: "scripthash", - scriptclass: btcscript.ScriptHashTy, - stringed: "scripthash", - }, - { - name: "multisigty", - scriptclass: btcscript.MultiSigTy, - stringed: "multisig", - }, - { - name: "nulldataty", - scriptclass: btcscript.NullDataTy, - stringed: "nulldata", - }, - { - name: "broken", - scriptclass: btcscript.ScriptClass(255), - stringed: "Invalid", - }, -} - func TestStringifyClass(t *testing.T) { - for _, test := range classStringifyTests { + t.Parallel() + + tests := []struct { + name string + scriptclass btcscript.ScriptClass + stringed string + }{ + { + name: "nonstandardty", + scriptclass: btcscript.NonStandardTy, + stringed: "nonstandard", + }, + { + name: "pubkey", + scriptclass: btcscript.PubKeyTy, + stringed: "pubkey", + }, + { + name: "pubkeyhash", + scriptclass: btcscript.PubKeyHashTy, + stringed: "pubkeyhash", + }, + { + name: "scripthash", + scriptclass: btcscript.ScriptHashTy, + stringed: "scripthash", + }, + { + name: "multisigty", + scriptclass: btcscript.MultiSigTy, + stringed: "multisig", + }, + { + name: "nulldataty", + scriptclass: btcscript.NullDataTy, + stringed: "nulldata", + }, + { + name: "broken", + scriptclass: btcscript.ScriptClass(255), + stringed: "Invalid", + }, + } + + for _, test := range tests { typeString := test.scriptclass.String() if typeString != test.stringed { t.Errorf("%s: got \"%s\" expected \"%s\"", test.name, @@ -2948,6 +2974,8 @@ func (b *bogusAddress) String() string { } func TestPayToAddrScript(t *testing.T) { + t.Parallel() + // 1MirQ9bwyQcGVJPwKUgapu5ouK2E2Ey4gX p2pkhMain, err := btcutil.NewAddressPubKeyHash([]byte{ 0xe3, 0x4c, 0xce, 0x70, 0xc8, 0x63, 0x73, 0x27, 0x3e, 0xfc, @@ -3102,6 +3130,8 @@ func TestPayToAddrScript(t *testing.T) { } func TestMultiSigScript(t *testing.T) { + t.Parallel() + // mainnet p2pk 13CG6SJ3yHUXo4Cr2RY4THLLJrNFuG3gUg p2pkCompressedMain, err := btcutil.NewAddressPubKey([]byte{ 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, @@ -3322,6 +3352,8 @@ func mkGetScript(scripts map[string][]byte) btcscript.ScriptDB { } func TestSignTxOutput(t *testing.T) { + t.Parallel() + // make key // make script based on key. // sign with magic pixie dust. @@ -4614,6 +4646,8 @@ func TestSignTxOutput(t *testing.T) { } func TestCalcMultiSigStats(t *testing.T) { + t.Parallel() + tests := []struct { name string script []byte @@ -4691,6 +4725,8 @@ func TestCalcMultiSigStats(t *testing.T) { } func TestHasCanonicalPushes(t *testing.T) { + t.Parallel() + tests := []struct { name string script []byte @@ -4723,6 +4759,8 @@ func TestHasCanonicalPushes(t *testing.T) { } func TestIsPushOnlyScript(t *testing.T) { + t.Parallel() + test := struct { name string script []byte diff --git a/stack_test.go b/stack_test.go index df58c28f..0da1f1d6 100644 --- a/stack_test.go +++ b/stack_test.go @@ -14,992 +14,992 @@ import ( "github.com/btcsuite/btcscript" ) -type stackTest struct { - name string - before [][]byte - operation func(*btcscript.Stack) error - expectedReturn error - after [][]byte -} - -var stackTests = []stackTest{ - { - "noop", - [][]byte{{1}, {2}, {3}, {4}, {5}}, - func(stack *btcscript.Stack) error { - return nil - }, - nil, - [][]byte{{1}, {2}, {3}, {4}, {5}}, - }, - { - "peek underflow (byte)", - [][]byte{{1}, {2}, {3}, {4}, {5}}, - func(stack *btcscript.Stack) error { - _, err := stack.PeekByteArray(5) - return err - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "peek underflow (int)", - [][]byte{{1}, {2}, {3}, {4}, {5}}, - func(stack *btcscript.Stack) error { - _, err := stack.PeekInt(5) - return err - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "peek underflow (bool)", - [][]byte{{1}, {2}, {3}, {4}, {5}}, - func(stack *btcscript.Stack) error { - _, err := stack.PeekBool(5) - return err - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "pop", - [][]byte{{1}, {2}, {3}, {4}, {5}}, - func(stack *btcscript.Stack) error { - val, err := stack.PopByteArray() - if err != nil { - return err - } - if !bytes.Equal(val, []byte{5}) { - return errors.New("not equal!") - } - return err - }, - nil, - [][]byte{{1}, {2}, {3}, {4}}, - }, - { - "pop", - [][]byte{{1}, {2}, {3}, {4}, {5}}, - func(stack *btcscript.Stack) error { - val, err := stack.PopByteArray() - if err != nil { - return err - } - if !bytes.Equal(val, []byte{5}) { - return errors.New("not equal!") - } - return err - }, - nil, - [][]byte{{1}, {2}, {3}, {4}}, - }, - { - "pop everything", - [][]byte{{1}, {2}, {3}, {4}, {5}}, - func(stack *btcscript.Stack) error { - for i := 0; i < 5; i++ { - _, err := stack.PopByteArray() - if err != nil { - return err - } - } - return nil - }, - nil, - [][]byte{}, - }, - { - "pop underflow", - [][]byte{{1}, {2}, {3}, {4}, {5}}, - func(stack *btcscript.Stack) error { - for i := 0; i < 6; i++ { - _, err := stack.PopByteArray() - if err != nil { - return err - } - } - return nil - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "pop bool", - [][]byte{{0}}, - func(stack *btcscript.Stack) error { - val, err := stack.PopBool() - if err != nil { - return err - } - - if val != false { - return errors.New("unexpected value") - } - return nil - }, - nil, - [][]byte{}, - }, - { - "pop bool", - [][]byte{{1}}, - func(stack *btcscript.Stack) error { - val, err := stack.PopBool() - if err != nil { - return err - } - - if val != true { - return errors.New("unexpected value") - } - return nil - }, - nil, - [][]byte{}, - }, - { - "pop bool", - [][]byte{}, - func(stack *btcscript.Stack) error { - _, err := stack.PopBool() - if err != nil { - return err - } - - return nil - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "popInt 0", - [][]byte{{0x0}}, - func(stack *btcscript.Stack) error { - v, err := stack.PopInt() - if err != nil { - return err - } - if v.Sign() != 0 { - return errors.New("0 != 0 on popInt") - } - return nil - }, - nil, - [][]byte{}, - }, - { - "popInt -0", - [][]byte{{0x80}}, - func(stack *btcscript.Stack) error { - v, err := stack.PopInt() - if err != nil { - return err - } - if v.Sign() != 0 { - return errors.New("-0 != 0 on popInt") - } - return nil - }, - nil, - [][]byte{}, - }, - { - "popInt 1", - [][]byte{{0x01}}, - func(stack *btcscript.Stack) error { - v, err := stack.PopInt() - if err != nil { - return err - } - if v.Cmp(big.NewInt(1)) != 0 { - return errors.New("1 != 1 on popInt") - } - return nil - }, - nil, - [][]byte{}, - }, - { - "popInt 1 leading 0", - [][]byte{{0x01, 0x00, 0x00, 0x00}}, - func(stack *btcscript.Stack) error { - v, err := stack.PopInt() - if err != nil { - return err - } - if v.Cmp(big.NewInt(1)) != 0 { - fmt.Printf("%v != %v\n", v, big.NewInt(1)) - return errors.New("1 != 1 on popInt") - } - return nil - }, - nil, - [][]byte{}, - }, - { - "popInt -1", - [][]byte{{0x81}}, - func(stack *btcscript.Stack) error { - v, err := stack.PopInt() - if err != nil { - return err - } - if v.Cmp(big.NewInt(-1)) != 0 { - return errors.New("1 != 1 on popInt") - } - return nil - }, - nil, - [][]byte{}, - }, - { - "popInt -1 leading 0", - [][]byte{{0x01, 0x00, 0x00, 0x80}}, - func(stack *btcscript.Stack) error { - v, err := stack.PopInt() - if err != nil { - return err - } - if v.Cmp(big.NewInt(-1)) != 0 { - fmt.Printf("%v != %v\n", v, big.NewInt(-1)) - return errors.New("-1 != -1 on popInt") - } - return nil - }, - nil, - [][]byte{}, - }, - // Triggers the multibyte case in asInt - { - "popInt -513", - [][]byte{{0x1, 0x82}}, - func(stack *btcscript.Stack) error { - v, err := stack.PopInt() - if err != nil { - return err - } - if v.Cmp(big.NewInt(-513)) != 0 { - fmt.Printf("%v != %v\n", v, big.NewInt(-513)) - return errors.New("1 != 1 on popInt") - } - return nil - }, - nil, - [][]byte{}, - }, - // Confirm that the asInt code doesn't modify the base data. - { - "peekint nomodify -1", - [][]byte{{0x01, 0x00, 0x00, 0x80}}, - func(stack *btcscript.Stack) error { - v, err := stack.PeekInt(0) - if err != nil { - return err - } - if v.Cmp(big.NewInt(-1)) != 0 { - fmt.Printf("%v != %v\n", v, big.NewInt(-1)) - return errors.New("-1 != -1 on popInt") - } - return nil - }, - nil, - [][]byte{{0x01, 0x00, 0x00, 0x80}}, - }, - { - "PushInt 0", - [][]byte{}, - func(stack *btcscript.Stack) error { - stack.PushInt(big.NewInt(0)) - return nil - }, - nil, - [][]byte{{}}, - }, - { - "PushInt 1", - [][]byte{}, - func(stack *btcscript.Stack) error { - stack.PushInt(big.NewInt(1)) - return nil - }, - nil, - [][]byte{{0x1}}, - }, - { - "PushInt -1", - [][]byte{}, - func(stack *btcscript.Stack) error { - stack.PushInt(big.NewInt(-1)) - return nil - }, - nil, - [][]byte{{0x81}}, - }, - { - "PushInt two bytes", - [][]byte{}, - func(stack *btcscript.Stack) error { - stack.PushInt(big.NewInt(256)) - return nil - }, - nil, - // little endian.. *sigh* - [][]byte{{0x00, 0x01}}, - }, - { - "PushInt leading zeros", - [][]byte{}, - func(stack *btcscript.Stack) error { - // this will have the highbit set - stack.PushInt(big.NewInt(128)) - return nil - }, - nil, - [][]byte{{0x80, 0x00}}, - }, - { - "dup", - [][]byte{{1}}, - func(stack *btcscript.Stack) error { - err := stack.DupN(1) - if err != nil { - return err - } - - return nil - }, - nil, - [][]byte{{1}, {1}}, - }, - { - "dup2", - [][]byte{{1}, {2}}, - func(stack *btcscript.Stack) error { - err := stack.DupN(2) - if err != nil { - return err - } - - return nil - }, - nil, - [][]byte{{1}, {2}, {1}, {2}}, - }, - { - "dup3", - [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { - err := stack.DupN(3) - if err != nil { - return err - } - - return nil - }, - nil, - [][]byte{{1}, {2}, {3}, {1}, {2}, {3}}, - }, - { - "dup0", - [][]byte{{1}}, - func(stack *btcscript.Stack) error { - err := stack.DupN(0) - if err != nil { - return err - } - - return nil - }, - btcscript.ErrStackInvalidArgs, - [][]byte{}, - }, - { - "dup-1", - [][]byte{{1}}, - func(stack *btcscript.Stack) error { - err := stack.DupN(-1) - if err != nil { - return err - } - - return nil - }, - btcscript.ErrStackInvalidArgs, - [][]byte{}, - }, - { - "dup too much", - [][]byte{{1}}, - func(stack *btcscript.Stack) error { - err := stack.DupN(2) - if err != nil { - return err - } - - return nil - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "dup-1", - [][]byte{{1}}, - func(stack *btcscript.Stack) error { - err := stack.DupN(-1) - if err != nil { - return err - } - - return nil - }, - btcscript.ErrStackInvalidArgs, - [][]byte{}, - }, - { - "PushBool true", - [][]byte{}, - func(stack *btcscript.Stack) error { - stack.PushBool(true) - - return nil - }, - nil, - [][]byte{{1}}, - }, - { - "PushBool false", - [][]byte{}, - func(stack *btcscript.Stack) error { - stack.PushBool(false) - - return nil - }, - nil, - [][]byte{{0}}, - }, - { - "PushBool PopBool", - [][]byte{}, - func(stack *btcscript.Stack) error { - stack.PushBool(true) - val, err := stack.PopBool() - if err != nil { - return err - } - if val != true { - return errors.New("unexpected value") - } - - return nil - }, - nil, - [][]byte{}, - }, - { - "PushBool PopBool 2", - [][]byte{}, - func(stack *btcscript.Stack) error { - stack.PushBool(false) - val, err := stack.PopBool() - if err != nil { - return err - } - if val != false { - return errors.New("unexpected value") - } - - return nil - }, - nil, - [][]byte{}, - }, - { - "PushInt PopBool", - [][]byte{}, - func(stack *btcscript.Stack) error { - stack.PushInt(big.NewInt(1)) - val, err := stack.PopBool() - if err != nil { - return err - } - if val != true { - return errors.New("unexpected value") - } - - return nil - }, - nil, - [][]byte{}, - }, - { - "PushInt PopBool 2", - [][]byte{}, - func(stack *btcscript.Stack) error { - stack.PushInt(big.NewInt(0)) - val, err := stack.PopBool() - if err != nil { - return err - } - if val != false { - return errors.New("unexpected value") - } - - return nil - }, - nil, - [][]byte{}, - }, - { - "PushInt PopBool 2", - [][]byte{}, - func(stack *btcscript.Stack) error { - stack.PushInt(big.NewInt(0)) - val, err := stack.PopBool() - if err != nil { - return err - } - if val != false { - return errors.New("unexpected value") - } - - return nil - }, - nil, - [][]byte{}, - }, - { - "Nip top", - [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { - return stack.NipN(0) - }, - nil, - [][]byte{{1}, {2}}, - }, - { - "Nip middle", - [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { - return stack.NipN(1) - }, - nil, - [][]byte{{1}, {3}}, - }, - { - "Nip low", - [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { - return stack.NipN(2) - }, - nil, - [][]byte{{2}, {3}}, - }, - { - "Nip too much", - [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { - // bite off more than we can chew - return stack.NipN(3) - }, - btcscript.ErrStackUnderflow, - [][]byte{{2}, {3}}, - }, - { - "Nip too much", - [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { - // bite off more than we can chew - return stack.NipN(3) - }, - btcscript.ErrStackUnderflow, - [][]byte{{2}, {3}}, - }, - { - "keep on tucking", - [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { - return stack.Tuck() - }, - nil, - [][]byte{{1}, {3}, {2}, {3}}, - }, - { - "a little tucked up", - [][]byte{{1}}, // too few arguments for tuck - func(stack *btcscript.Stack) error { - return stack.Tuck() - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "all tucked up", - [][]byte{}, // too few arguments for tuck - func(stack *btcscript.Stack) error { - return stack.Tuck() - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "drop 1", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.DropN(1) - }, - nil, - [][]byte{{1}, {2}, {3}}, - }, - { - "drop 2", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.DropN(2) - }, - nil, - [][]byte{{1}, {2}}, - }, - { - "drop 3", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.DropN(3) - }, - nil, - [][]byte{{1}}, - }, - { - "drop 4", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.DropN(4) - }, - nil, - [][]byte{}, - }, - { - "drop 4/5", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.DropN(5) - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "drop invalid", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.DropN(0) - }, - btcscript.ErrStackInvalidArgs, - [][]byte{}, - }, - { - "Rot1", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.RotN(1) - }, - nil, - [][]byte{{1}, {3}, {4}, {2}}, - }, - { - "Rot2", - [][]byte{{1}, {2}, {3}, {4}, {5}, {6}}, - func(stack *btcscript.Stack) error { - return stack.RotN(2) - }, - nil, - [][]byte{{3}, {4}, {5}, {6}, {1}, {2}}, - }, - { - "Rot too little", - [][]byte{{1}, {2}}, - func(stack *btcscript.Stack) error { - return stack.RotN(1) - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "Rot0", - [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { - return stack.RotN(0) - }, - btcscript.ErrStackInvalidArgs, - [][]byte{}, - }, - { - "Swap1", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.SwapN(1) - }, - nil, - [][]byte{{1}, {2}, {4}, {3}}, - }, - { - "Swap2", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.SwapN(2) - }, - nil, - [][]byte{{3}, {4}, {1}, {2}}, - }, - { - "Swap too little", - [][]byte{{1}}, - func(stack *btcscript.Stack) error { - return stack.SwapN(1) - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "Swap0", - [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { - return stack.SwapN(0) - }, - btcscript.ErrStackInvalidArgs, - [][]byte{}, - }, - { - "Over1", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.OverN(1) - }, - nil, - [][]byte{{1}, {2}, {3}, {4}, {3}}, - }, - { - "Over2", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.OverN(2) - }, - nil, - [][]byte{{1}, {2}, {3}, {4}, {1}, {2}}, - }, - { - "Over too little", - [][]byte{{1}}, - func(stack *btcscript.Stack) error { - return stack.OverN(1) - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "Over0", - [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { - return stack.OverN(0) - }, - btcscript.ErrStackInvalidArgs, - [][]byte{}, - }, - { - "Pick1", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.PickN(1) - }, - nil, - [][]byte{{1}, {2}, {3}, {4}, {3}}, - }, - { - "Pick2", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.PickN(2) - }, - nil, - [][]byte{{1}, {2}, {3}, {4}, {2}}, - }, - { - "Pick too little", - [][]byte{{1}}, - func(stack *btcscript.Stack) error { - return stack.PickN(1) - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "Roll1", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.RollN(1) - }, - nil, - [][]byte{{1}, {2}, {4}, {3}}, - }, - { - "Roll2", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.RollN(2) - }, - nil, - [][]byte{{1}, {3}, {4}, {2}}, - }, - { - "Roll too little", - [][]byte{{1}}, - func(stack *btcscript.Stack) error { - return stack.RollN(1) - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "Peek bool", - [][]byte{{1}}, - func(stack *btcscript.Stack) error { - // Peek bool is otherwise pretty well tested, just check - // it works. - val, err := stack.PeekBool(0) - if err != nil { - return err - } - if val != true { - return errors.New("invalid result") - } - return nil - }, - nil, - [][]byte{{1}}, - }, - { - "Peek bool 2", - [][]byte{{0}}, - func(stack *btcscript.Stack) error { - // Peek bool is otherwise pretty well tested, just check - // it works. - val, err := stack.PeekBool(0) - if err != nil { - return err - } - if val != false { - return errors.New("invalid result") - } - return nil - }, - nil, - [][]byte{{0}}, - }, - { - "Peek int", - [][]byte{{1}}, - func(stack *btcscript.Stack) error { - // Peek int is otherwise pretty well tested, just check - // it works. - val, err := stack.PeekInt(0) - if err != nil { - return err - } - if val.Cmp(big.NewInt(1)) != 0 { - return errors.New("invalid result") - } - return nil - }, - nil, - [][]byte{{1}}, - }, - { - "Peek int 2", - [][]byte{{0}}, - func(stack *btcscript.Stack) error { - // Peek int is otherwise pretty well tested, just check - // it works. - val, err := stack.PeekInt(0) - if err != nil { - return err - } - if val.Cmp(big.NewInt(0)) != 0 { - return errors.New("invalid result") - } - return nil - }, - nil, - [][]byte{{0}}, - }, - { - "pop int", - [][]byte{}, - func(stack *btcscript.Stack) error { - stack.PushInt(big.NewInt(1)) - // Peek int is otherwise pretty well tested, just check - // it works. - val, err := stack.PopInt() - if err != nil { - return err - } - if val.Cmp(big.NewInt(1)) != 0 { - return errors.New("invalid result") - } - return nil - }, - nil, - [][]byte{}, - }, - { - "pop empty", - [][]byte{}, - func(stack *btcscript.Stack) error { - // Peek int is otherwise pretty well tested, just check - // it works. - _, err := stack.PopInt() - return err - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, -} - -func doTest(t *testing.T, test stackTest) { - stack := btcscript.Stack{} - - for i := range test.before { - stack.PushByteArray(test.before[i]) - } - err := test.operation(&stack) - if err != test.expectedReturn { - t.Errorf("%s: operation return not what expected: %v vs %v", - test.name, err, test.expectedReturn) - } - if err != nil { - return - } - if len(test.after) != stack.Depth() { - t.Errorf("%s: stack depth doesn't match expected: %v vs %v", - test.name, len(test.after), stack.Depth()) - } - for i := range test.after { - val, err := stack.PeekByteArray(stack.Depth() - i - 1) - if err != nil { - t.Errorf("%s: can't peek %dth stack entry: %v", - test.name, i, err) - break - } - - if !bytes.Equal(val, test.after[i]) { - t.Errorf("%s: %dth stack entry doesn't match "+ - "expected: %v vs %v", test.name, i, val, - test.after[i]) - break - } - } -} - +// TestStack tests that all of the stack operations work as expected. func TestStack(t *testing.T) { - for i := range stackTests { - doTest(t, stackTests[i]) + t.Parallel() + + tests := []struct { + name string + before [][]byte + operation func(*btcscript.Stack) error + expectedReturn error + after [][]byte + }{ + { + "noop", + [][]byte{{1}, {2}, {3}, {4}, {5}}, + func(stack *btcscript.Stack) error { + return nil + }, + nil, + [][]byte{{1}, {2}, {3}, {4}, {5}}, + }, + { + "peek underflow (byte)", + [][]byte{{1}, {2}, {3}, {4}, {5}}, + func(stack *btcscript.Stack) error { + _, err := stack.PeekByteArray(5) + return err + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "peek underflow (int)", + [][]byte{{1}, {2}, {3}, {4}, {5}}, + func(stack *btcscript.Stack) error { + _, err := stack.PeekInt(5) + return err + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "peek underflow (bool)", + [][]byte{{1}, {2}, {3}, {4}, {5}}, + func(stack *btcscript.Stack) error { + _, err := stack.PeekBool(5) + return err + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "pop", + [][]byte{{1}, {2}, {3}, {4}, {5}}, + func(stack *btcscript.Stack) error { + val, err := stack.PopByteArray() + if err != nil { + return err + } + if !bytes.Equal(val, []byte{5}) { + return errors.New("not equal!") + } + return err + }, + nil, + [][]byte{{1}, {2}, {3}, {4}}, + }, + { + "pop", + [][]byte{{1}, {2}, {3}, {4}, {5}}, + func(stack *btcscript.Stack) error { + val, err := stack.PopByteArray() + if err != nil { + return err + } + if !bytes.Equal(val, []byte{5}) { + return errors.New("not equal!") + } + return err + }, + nil, + [][]byte{{1}, {2}, {3}, {4}}, + }, + { + "pop everything", + [][]byte{{1}, {2}, {3}, {4}, {5}}, + func(stack *btcscript.Stack) error { + for i := 0; i < 5; i++ { + _, err := stack.PopByteArray() + if err != nil { + return err + } + } + return nil + }, + nil, + [][]byte{}, + }, + { + "pop underflow", + [][]byte{{1}, {2}, {3}, {4}, {5}}, + func(stack *btcscript.Stack) error { + for i := 0; i < 6; i++ { + _, err := stack.PopByteArray() + if err != nil { + return err + } + } + return nil + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "pop bool", + [][]byte{{0}}, + func(stack *btcscript.Stack) error { + val, err := stack.PopBool() + if err != nil { + return err + } + + if val != false { + return errors.New("unexpected value") + } + return nil + }, + nil, + [][]byte{}, + }, + { + "pop bool", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + val, err := stack.PopBool() + if err != nil { + return err + } + + if val != true { + return errors.New("unexpected value") + } + return nil + }, + nil, + [][]byte{}, + }, + { + "pop bool", + [][]byte{}, + func(stack *btcscript.Stack) error { + _, err := stack.PopBool() + if err != nil { + return err + } + + return nil + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "popInt 0", + [][]byte{{0x0}}, + func(stack *btcscript.Stack) error { + v, err := stack.PopInt() + if err != nil { + return err + } + if v.Sign() != 0 { + return errors.New("0 != 0 on popInt") + } + return nil + }, + nil, + [][]byte{}, + }, + { + "popInt -0", + [][]byte{{0x80}}, + func(stack *btcscript.Stack) error { + v, err := stack.PopInt() + if err != nil { + return err + } + if v.Sign() != 0 { + return errors.New("-0 != 0 on popInt") + } + return nil + }, + nil, + [][]byte{}, + }, + { + "popInt 1", + [][]byte{{0x01}}, + func(stack *btcscript.Stack) error { + v, err := stack.PopInt() + if err != nil { + return err + } + if v.Cmp(big.NewInt(1)) != 0 { + return errors.New("1 != 1 on popInt") + } + return nil + }, + nil, + [][]byte{}, + }, + { + "popInt 1 leading 0", + [][]byte{{0x01, 0x00, 0x00, 0x00}}, + func(stack *btcscript.Stack) error { + v, err := stack.PopInt() + if err != nil { + return err + } + if v.Cmp(big.NewInt(1)) != 0 { + fmt.Printf("%v != %v\n", v, big.NewInt(1)) + return errors.New("1 != 1 on popInt") + } + return nil + }, + nil, + [][]byte{}, + }, + { + "popInt -1", + [][]byte{{0x81}}, + func(stack *btcscript.Stack) error { + v, err := stack.PopInt() + if err != nil { + return err + } + if v.Cmp(big.NewInt(-1)) != 0 { + return errors.New("1 != 1 on popInt") + } + return nil + }, + nil, + [][]byte{}, + }, + { + "popInt -1 leading 0", + [][]byte{{0x01, 0x00, 0x00, 0x80}}, + func(stack *btcscript.Stack) error { + v, err := stack.PopInt() + if err != nil { + return err + } + if v.Cmp(big.NewInt(-1)) != 0 { + fmt.Printf("%v != %v\n", v, big.NewInt(-1)) + return errors.New("-1 != -1 on popInt") + } + return nil + }, + nil, + [][]byte{}, + }, + // Triggers the multibyte case in asInt + { + "popInt -513", + [][]byte{{0x1, 0x82}}, + func(stack *btcscript.Stack) error { + v, err := stack.PopInt() + if err != nil { + return err + } + if v.Cmp(big.NewInt(-513)) != 0 { + fmt.Printf("%v != %v\n", v, big.NewInt(-513)) + return errors.New("1 != 1 on popInt") + } + return nil + }, + nil, + [][]byte{}, + }, + // Confirm that the asInt code doesn't modify the base data. + { + "peekint nomodify -1", + [][]byte{{0x01, 0x00, 0x00, 0x80}}, + func(stack *btcscript.Stack) error { + v, err := stack.PeekInt(0) + if err != nil { + return err + } + if v.Cmp(big.NewInt(-1)) != 0 { + fmt.Printf("%v != %v\n", v, big.NewInt(-1)) + return errors.New("-1 != -1 on popInt") + } + return nil + }, + nil, + [][]byte{{0x01, 0x00, 0x00, 0x80}}, + }, + { + "PushInt 0", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushInt(big.NewInt(0)) + return nil + }, + nil, + [][]byte{{}}, + }, + { + "PushInt 1", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushInt(big.NewInt(1)) + return nil + }, + nil, + [][]byte{{0x1}}, + }, + { + "PushInt -1", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushInt(big.NewInt(-1)) + return nil + }, + nil, + [][]byte{{0x81}}, + }, + { + "PushInt two bytes", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushInt(big.NewInt(256)) + return nil + }, + nil, + // little endian.. *sigh* + [][]byte{{0x00, 0x01}}, + }, + { + "PushInt leading zeros", + [][]byte{}, + func(stack *btcscript.Stack) error { + // this will have the highbit set + stack.PushInt(big.NewInt(128)) + return nil + }, + nil, + [][]byte{{0x80, 0x00}}, + }, + { + "dup", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + err := stack.DupN(1) + if err != nil { + return err + } + + return nil + }, + nil, + [][]byte{{1}, {1}}, + }, + { + "dup2", + [][]byte{{1}, {2}}, + func(stack *btcscript.Stack) error { + err := stack.DupN(2) + if err != nil { + return err + } + + return nil + }, + nil, + [][]byte{{1}, {2}, {1}, {2}}, + }, + { + "dup3", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + err := stack.DupN(3) + if err != nil { + return err + } + + return nil + }, + nil, + [][]byte{{1}, {2}, {3}, {1}, {2}, {3}}, + }, + { + "dup0", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + err := stack.DupN(0) + if err != nil { + return err + } + + return nil + }, + btcscript.ErrStackInvalidArgs, + [][]byte{}, + }, + { + "dup-1", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + err := stack.DupN(-1) + if err != nil { + return err + } + + return nil + }, + btcscript.ErrStackInvalidArgs, + [][]byte{}, + }, + { + "dup too much", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + err := stack.DupN(2) + if err != nil { + return err + } + + return nil + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "dup-1", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + err := stack.DupN(-1) + if err != nil { + return err + } + + return nil + }, + btcscript.ErrStackInvalidArgs, + [][]byte{}, + }, + { + "PushBool true", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushBool(true) + + return nil + }, + nil, + [][]byte{{1}}, + }, + { + "PushBool false", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushBool(false) + + return nil + }, + nil, + [][]byte{{0}}, + }, + { + "PushBool PopBool", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushBool(true) + val, err := stack.PopBool() + if err != nil { + return err + } + if val != true { + return errors.New("unexpected value") + } + + return nil + }, + nil, + [][]byte{}, + }, + { + "PushBool PopBool 2", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushBool(false) + val, err := stack.PopBool() + if err != nil { + return err + } + if val != false { + return errors.New("unexpected value") + } + + return nil + }, + nil, + [][]byte{}, + }, + { + "PushInt PopBool", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushInt(big.NewInt(1)) + val, err := stack.PopBool() + if err != nil { + return err + } + if val != true { + return errors.New("unexpected value") + } + + return nil + }, + nil, + [][]byte{}, + }, + { + "PushInt PopBool 2", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushInt(big.NewInt(0)) + val, err := stack.PopBool() + if err != nil { + return err + } + if val != false { + return errors.New("unexpected value") + } + + return nil + }, + nil, + [][]byte{}, + }, + { + "PushInt PopBool 2", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushInt(big.NewInt(0)) + val, err := stack.PopBool() + if err != nil { + return err + } + if val != false { + return errors.New("unexpected value") + } + + return nil + }, + nil, + [][]byte{}, + }, + { + "Nip top", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + return stack.NipN(0) + }, + nil, + [][]byte{{1}, {2}}, + }, + { + "Nip middle", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + return stack.NipN(1) + }, + nil, + [][]byte{{1}, {3}}, + }, + { + "Nip low", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + return stack.NipN(2) + }, + nil, + [][]byte{{2}, {3}}, + }, + { + "Nip too much", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + // bite off more than we can chew + return stack.NipN(3) + }, + btcscript.ErrStackUnderflow, + [][]byte{{2}, {3}}, + }, + { + "Nip too much", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + // bite off more than we can chew + return stack.NipN(3) + }, + btcscript.ErrStackUnderflow, + [][]byte{{2}, {3}}, + }, + { + "keep on tucking", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + return stack.Tuck() + }, + nil, + [][]byte{{1}, {3}, {2}, {3}}, + }, + { + "a little tucked up", + [][]byte{{1}}, // too few arguments for tuck + func(stack *btcscript.Stack) error { + return stack.Tuck() + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "all tucked up", + [][]byte{}, // too few arguments for tuck + func(stack *btcscript.Stack) error { + return stack.Tuck() + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "drop 1", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.DropN(1) + }, + nil, + [][]byte{{1}, {2}, {3}}, + }, + { + "drop 2", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.DropN(2) + }, + nil, + [][]byte{{1}, {2}}, + }, + { + "drop 3", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.DropN(3) + }, + nil, + [][]byte{{1}}, + }, + { + "drop 4", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.DropN(4) + }, + nil, + [][]byte{}, + }, + { + "drop 4/5", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.DropN(5) + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "drop invalid", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.DropN(0) + }, + btcscript.ErrStackInvalidArgs, + [][]byte{}, + }, + { + "Rot1", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.RotN(1) + }, + nil, + [][]byte{{1}, {3}, {4}, {2}}, + }, + { + "Rot2", + [][]byte{{1}, {2}, {3}, {4}, {5}, {6}}, + func(stack *btcscript.Stack) error { + return stack.RotN(2) + }, + nil, + [][]byte{{3}, {4}, {5}, {6}, {1}, {2}}, + }, + { + "Rot too little", + [][]byte{{1}, {2}}, + func(stack *btcscript.Stack) error { + return stack.RotN(1) + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "Rot0", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + return stack.RotN(0) + }, + btcscript.ErrStackInvalidArgs, + [][]byte{}, + }, + { + "Swap1", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.SwapN(1) + }, + nil, + [][]byte{{1}, {2}, {4}, {3}}, + }, + { + "Swap2", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.SwapN(2) + }, + nil, + [][]byte{{3}, {4}, {1}, {2}}, + }, + { + "Swap too little", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + return stack.SwapN(1) + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "Swap0", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + return stack.SwapN(0) + }, + btcscript.ErrStackInvalidArgs, + [][]byte{}, + }, + { + "Over1", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.OverN(1) + }, + nil, + [][]byte{{1}, {2}, {3}, {4}, {3}}, + }, + { + "Over2", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.OverN(2) + }, + nil, + [][]byte{{1}, {2}, {3}, {4}, {1}, {2}}, + }, + { + "Over too little", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + return stack.OverN(1) + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "Over0", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + return stack.OverN(0) + }, + btcscript.ErrStackInvalidArgs, + [][]byte{}, + }, + { + "Pick1", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.PickN(1) + }, + nil, + [][]byte{{1}, {2}, {3}, {4}, {3}}, + }, + { + "Pick2", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.PickN(2) + }, + nil, + [][]byte{{1}, {2}, {3}, {4}, {2}}, + }, + { + "Pick too little", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + return stack.PickN(1) + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "Roll1", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.RollN(1) + }, + nil, + [][]byte{{1}, {2}, {4}, {3}}, + }, + { + "Roll2", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.RollN(2) + }, + nil, + [][]byte{{1}, {3}, {4}, {2}}, + }, + { + "Roll too little", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + return stack.RollN(1) + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "Peek bool", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + // Peek bool is otherwise pretty well tested, + // just check it works. + val, err := stack.PeekBool(0) + if err != nil { + return err + } + if val != true { + return errors.New("invalid result") + } + return nil + }, + nil, + [][]byte{{1}}, + }, + { + "Peek bool 2", + [][]byte{{0}}, + func(stack *btcscript.Stack) error { + // Peek bool is otherwise pretty well tested, + // just check it works. + val, err := stack.PeekBool(0) + if err != nil { + return err + } + if val != false { + return errors.New("invalid result") + } + return nil + }, + nil, + [][]byte{{0}}, + }, + { + "Peek int", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + // Peek int is otherwise pretty well tested, + // just check it works. + val, err := stack.PeekInt(0) + if err != nil { + return err + } + if val.Cmp(big.NewInt(1)) != 0 { + return errors.New("invalid result") + } + return nil + }, + nil, + [][]byte{{1}}, + }, + { + "Peek int 2", + [][]byte{{0}}, + func(stack *btcscript.Stack) error { + // Peek int is otherwise pretty well tested, + // just check it works. + val, err := stack.PeekInt(0) + if err != nil { + return err + } + if val.Cmp(big.NewInt(0)) != 0 { + return errors.New("invalid result") + } + return nil + }, + nil, + [][]byte{{0}}, + }, + { + "pop int", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushInt(big.NewInt(1)) + // Peek int is otherwise pretty well tested, + // just check it works. + val, err := stack.PopInt() + if err != nil { + return err + } + if val.Cmp(big.NewInt(1)) != 0 { + return errors.New("invalid result") + } + return nil + }, + nil, + [][]byte{}, + }, + { + "pop empty", + [][]byte{}, + func(stack *btcscript.Stack) error { + // Peek int is otherwise pretty well tested, + // just check it works. + _, err := stack.PopInt() + return err + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + } + + for _, test := range tests { + stack := btcscript.Stack{} + + for i := range test.before { + stack.PushByteArray(test.before[i]) + } + err := test.operation(&stack) + if err != test.expectedReturn { + t.Errorf("%s: operation return not what expected: %v "+ + "vs %v", test.name, err, test.expectedReturn) + } + if err != nil { + continue + } + + if len(test.after) != stack.Depth() { + t.Errorf("%s: stack depth doesn't match expected: %v "+ + "vs %v", test.name, len(test.after), + stack.Depth()) + } + + for i := range test.after { + val, err := stack.PeekByteArray(stack.Depth() - i - 1) + if err != nil { + t.Errorf("%s: can't peek %dth stack entry: %v", + test.name, i, err) + break + } + + if !bytes.Equal(val, test.after[i]) { + t.Errorf("%s: %dth stack entry doesn't match "+ + "expected: %v vs %v", test.name, i, val, + test.after[i]) + break + } + } } } From d7dbe25d9713a39f59980094ee20aff050f39f6b Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 29 Jan 2015 16:26:20 -0600 Subject: [PATCH 172/174] Fix test error verbs found by go vet in the tests. --- script_test.go | 4 ++-- scriptbuilder_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/script_test.go b/script_test.go index 388bd8d2..e8d9c372 100644 --- a/script_test.go +++ b/script_test.go @@ -4752,7 +4752,7 @@ func TestHasCanonicalPushes(t *testing.T) { for i, test := range tests { if btcscript.HasCanonicalPushes(test.script) != test.expected { t.Errorf("HasCanonicalPushes #%d (%s) wrong result\n"+ - "got: %x\nwant: %x", i, test.name, true, + "got: %v\nwant: %v", i, test.name, true, test.expected) } } @@ -4778,7 +4778,7 @@ func TestIsPushOnlyScript(t *testing.T) { if btcscript.IsPushOnlyScript(test.script) != test.expected { t.Errorf("IsPushOnlyScript (%s) wrong result\n"+ - "got: %x\nwant: %x", test.name, true, + "got: %v\nwant: %v", test.name, true, test.expected) } } diff --git a/scriptbuilder_test.go b/scriptbuilder_test.go index 265ba882..198dfda2 100644 --- a/scriptbuilder_test.go +++ b/scriptbuilder_test.go @@ -173,7 +173,7 @@ func TestScriptBuilderAddUint64(t *testing.T) { result, err := builder.Script() if err != nil { t.Errorf("ScriptBuilder.AddUint64 #%d (%s) unexpected "+ - "error: %v", err) + "error: %v", i, test.name, err) continue } if !bytes.Equal(result, test.expected) { From 115cea21096b2e4464e2f5ae58f1d35cc9a5edcd Mon Sep 17 00:00:00 2001 From: David Hill Date: Thu, 29 Jan 2015 15:30:21 -0500 Subject: [PATCH 173/174] Add new flag ScriptVerifySigPushOnly. The ScriptVerifySigPushOnly flag enforces signature scripts to only contain pushed data. This is rule 2 of BIP0062. Mimics Bitcoin Core commit d752ba86c1872f64a4641cf77008826d32bde65f --- data/script_invalid.json | 22 ++++- data/script_valid.json | 16 +++- internal_test.go | 50 ++++++++--- script.go | 8 ++ test_coverage.txt | 180 +++++++++++++++++++-------------------- 5 files changed, 173 insertions(+), 103 deletions(-) diff --git a/data/script_invalid.json b/data/script_invalid.json index 3574b9d1..4f1d5543 100644 --- a/data/script_invalid.json +++ b/data/script_invalid.json @@ -389,5 +389,25 @@ ["0 0x01 0x50", "HASH160 0x14 0xece424a6bb6ddf4db592c0faed60685047a361b1 EQUAL", "P2SH,STRICTENC", "OP_RESERVED in P2SH should fail"], ["0 0x01 VER", "HASH160 0x14 0x0f4d7845db968f2a81b530b6f3c1d6246d4c7e01 EQUAL", "P2SH,STRICTENC", "OP_VER in P2SH should fail"], -["0x00", "'00' EQUAL", "P2SH,STRICTENC", "Basic OP_0 execution"] +["0x00", "'00' EQUAL", "P2SH,STRICTENC", "Basic OP_0 execution"], + +[ + "0 0x47 0x3044022035341cc377b19138f944f90c45772cb06338c6d56a4c0c31a65bf1a8a105fadc022046dd232850b6bacb25879c9da82a7a628982aa19d055f1753468f68047662e0301 DUP", + "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", + "SIGPUSHONLY", + "2-of-2 with two identical keys and sigs pushed using OP_DUP" +], +[ + "0x47 0x304402204d8b99eea2f53382fd67e0dbc8ed0596bd614aa0dad6bc6843c7860c79b901c3022062f022a71993013e3d9b22302a8e4b40109d7bb057aeb250b9aab2197b3e96b801 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", + "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", + "", + "P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY" +], +[ + "0x47 0x30440220078c887c33abc67fbbd827ceb3f661c1c459e78218161b652f23e3ca76cfabbd022047df245eacb8a88d8c5ca7b5228e3b4d070c102d2f542433362d3f443cd24eda01 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", + "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", + "SIGPUSHONLY", + "P2SH(P2PK) with non-push scriptSig" +] + ] diff --git a/data/script_valid.json b/data/script_valid.json index 473bd37b..db62b926 100644 --- a/data/script_valid.json +++ b/data/script_valid.json @@ -522,5 +522,19 @@ "P2SH,STRICTENC", "Basic PUSHDATA1 signedness check"], -["0x00", "SIZE 0 EQUAL", "P2SH,STRICTENC", "Basic OP_0 execution"] +["0x00", "SIZE 0 EQUAL", "P2SH,STRICTENC", "Basic OP_0 execution"], + +[ + "0 0x47 0x3044022002a27769ee33db258bdf7a3792e7da4143ec4001b551f73e6a190b8d1bde449d02206742c56ccd94a7a2e16ca52fc1ae4a0aa122b0014a867a80de104f9cb18e472c01 DUP", + "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", + "", + "2-of-2 with two identical keys and sigs pushed using OP_DUP but no SIGPUSHONLY" +], +[ + "0 0x47 0x304402203acf75dd59bbef171aeeedae4f1020b824195820db82575c2b323b8899f95de9022067df297d3a5fad049ba0bb81255d0e495643cbcf9abae9e396988618bc0c6dfe01 0x47 0x304402205f8b859230c1cab7d4e8de38ff244d2ebe046b64e8d3f4219b01e483c203490a022071bdc488e31b557f7d9e5c8a8bec90dc92289ca70fa317685f4f140e38b30c4601", + "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", + "SIGPUSHONLY", + "2-of-2 with two identical keys and sigs pushed" +] + ] diff --git a/internal_test.go b/internal_test.go index 4f74e1f1..fa2bf539 100644 --- a/internal_test.go +++ b/internal_test.go @@ -3796,6 +3796,32 @@ func ParseShortForm(script string) ([]byte, error) { return builder.Script() } +// createSpendTx generates a basic spending transaction given the passed +// signature and public key scripts. +func createSpendingTx(sigScript, pkScript []byte) (*btcwire.MsgTx, error) { + coinbaseTx := btcwire.NewMsgTx() + + outPoint := btcwire.NewOutPoint(&btcwire.ShaHash{}, ^uint32(0)) + txIn := btcwire.NewTxIn(outPoint, []byte{OP_0, OP_0}) + txOut := btcwire.NewTxOut(0, pkScript) + coinbaseTx.AddTxIn(txIn) + coinbaseTx.AddTxOut(txOut) + + spendingTx := btcwire.NewMsgTx() + coinbaseTxSha, err := coinbaseTx.TxSha() + if err != nil { + return nil, err + } + outPoint = btcwire.NewOutPoint(&coinbaseTxSha, 0) + txIn = btcwire.NewTxIn(outPoint, sigScript) + txOut = btcwire.NewTxOut(0, nil) + + spendingTx.AddTxIn(txIn) + spendingTx.AddTxOut(txOut) + + return spendingTx, nil +} + func TestBitcoindInvalidTests(t *testing.T) { file, err := ioutil.ReadFile("data/script_invalid.json") if err != nil { @@ -3810,7 +3836,6 @@ func TestBitcoindInvalidTests(t *testing.T) { err) return } - tx := btcwire.NewMsgTx() for x, test := range tests { // Skip comments if len(test) == 1 { @@ -3827,19 +3852,21 @@ func TestBitcoindInvalidTests(t *testing.T) { t.Errorf("%s: can't parse scriptSig; %v", name, err) continue } - scriptPubKey, err := ParseShortForm(test[1]) if err != nil { t.Errorf("%s: can't parse scriptPubkey; %v", name, err) continue } - flags, err := parseScriptFlags(test[2]) if err != nil { t.Errorf("%s: %v", name, err) continue } - + tx, err := createSpendingTx(scriptSig, scriptPubKey) + if err != nil { + t.Errorf("createSpendingTx failed on test %s: %v", name, err) + continue + } s, err := NewScript(scriptSig, scriptPubKey, 0, tx, flags) if err == nil { if err := s.Execute(); err == nil { @@ -3865,7 +3892,6 @@ func TestBitcoindValidTests(t *testing.T) { err) return } - tx := btcwire.NewMsgTx() for x, test := range tests { // Skip comments if len(test) == 1 { @@ -3877,31 +3903,31 @@ func TestBitcoindValidTests(t *testing.T) { x) continue } - scriptSig, err := ParseShortForm(test[0]) if err != nil { t.Errorf("%s: can't parse scriptSig; %v", name, err) continue } - scriptPubKey, err := ParseShortForm(test[1]) if err != nil { t.Errorf("%s: can't parse scriptPubkey; %v", name, err) continue } - flags, err := parseScriptFlags(test[2]) if err != nil { t.Errorf("%s: %v", name, err) continue } - + tx, err := createSpendingTx(scriptSig, scriptPubKey) + if err != nil { + t.Errorf("createSpendingTx failed on test %s: %v", name, err) + continue + } s, err := NewScript(scriptSig, scriptPubKey, 0, tx, flags) if err != nil { t.Errorf("%s failed to create script: %v", name, err) continue } - err = s.Execute() if err != nil { t.Errorf("%s failed to execute: %v", name, err) @@ -4205,12 +4231,14 @@ func parseScriptFlags(flagStr string) (ScriptFlags, error) { switch flag { case "DISCOURAGE_UPGRADABLE_NOPS": flags |= ScriptDiscourageUpgradableNops - case "NONE": + case "", "NONE": // Nothing. case "NULLDUMMY": flags |= ScriptStrictMultiSig case "P2SH": flags |= ScriptBip16 + case "SIGPUSHONLY": + flags |= ScriptVerifySigPushOnly case "STRICTENC": // This is always set. default: diff --git a/script.go b/script.go index 0a719e69..86d71ea9 100644 --- a/script.go +++ b/script.go @@ -522,6 +522,10 @@ const ( // checks. This flag is only applied when the above opcodes are // executed. ScriptDiscourageUpgradableNops + + // ScriptVerifySigPushOnly defines that signature scripts must contain + // only pushed data. This is rule 2 of BIP0062. + ScriptVerifySigPushOnly ) // NewScript returns a new script engine for the provided tx and input idx with @@ -530,6 +534,10 @@ const ( // pay-to-script hash transactions will be fully validated. func NewScript(scriptSig []byte, scriptPubKey []byte, txidx int, tx *btcwire.MsgTx, flags ScriptFlags) (*Script, error) { var m Script + if flags&ScriptVerifySigPushOnly == ScriptVerifySigPushOnly && !IsPushOnlyScript(scriptSig) { + return nil, ErrStackNonPushOnly + } + scripts := [][]byte{scriptSig, scriptPubKey} m.scripts = make([][]parsedOpcode, len(scripts)) for i, scr := range scripts { diff --git a/test_coverage.txt b/test_coverage.txt index cc8ff18e..972b97c8 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -1,67 +1,66 @@ github.com/btcsuite/btcscript/script.go calcScriptHash 100.00% (39/39) github.com/btcsuite/btcscript/script.go Script.Step 100.00% (37/37) -github.com/btcsuite/btcscript/script.go parseScriptTemplate 100.00% (29/29) github.com/btcsuite/btcscript/opcode.go opcodeCheckSig 100.00% (29/29) -github.com/btcsuite/btcscript/script.go NewScript 100.00% (27/27) +github.com/btcsuite/btcscript/script.go parseScriptTemplate 100.00% (29/29) +github.com/btcsuite/btcscript/script.go NewScript 100.00% (29/29) github.com/btcsuite/btcscript/address.go ExtractPkScriptAddrs 100.00% (27/27) github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.addData 100.00% (25/25) github.com/btcsuite/btcscript/script.go CalcScriptInfo 100.00% (25/25) -github.com/btcsuite/btcscript/stack.go asInt 100.00% (23/23) github.com/btcsuite/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23) +github.com/btcsuite/btcscript/stack.go asInt 100.00% (23/23) github.com/btcsuite/btcscript/opcode.go parsedOpcode.disabled 100.00% (17/17) github.com/btcsuite/btcscript/opcode.go parsedOpcode.print 100.00% (16/16) github.com/btcsuite/btcscript/stack.go Stack.nipN 100.00% (15/15) github.com/btcsuite/btcscript/scriptbuilder.go canonicalDataSize 100.00% (14/14) github.com/btcsuite/btcscript/stack.go fromInt 100.00% (14/14) -github.com/btcsuite/btcscript/opcode.go opcodeWithin 100.00% (13/13) github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.AddUint64 100.00% (13/13) -github.com/btcsuite/btcscript/opcode.go parsedOpcode.exec 100.00% (13/13) -github.com/btcsuite/btcscript/script.go isMultiSig 100.00% (13/13) -github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.AddInt64 100.00% (13/13) github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.AddData 100.00% (13/13) +github.com/btcsuite/btcscript/script.go isMultiSig 100.00% (13/13) +github.com/btcsuite/btcscript/opcode.go opcodeWithin 100.00% (13/13) +github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.AddInt64 100.00% (13/13) +github.com/btcsuite/btcscript/opcode.go parsedOpcode.exec 100.00% (13/13) github.com/btcsuite/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) -github.com/btcsuite/btcscript/opcode.go opcodeNotIf 100.00% (11/11) -github.com/btcsuite/btcscript/script.go typeOfScript 100.00% (11/11) github.com/btcsuite/btcscript/opcode.go opcodeIf 100.00% (11/11) +github.com/btcsuite/btcscript/opcode.go opcodeNotIf 100.00% (11/11) github.com/btcsuite/btcscript/script.go PayToAddrScript 100.00% (11/11) -github.com/btcsuite/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) +github.com/btcsuite/btcscript/script.go typeOfScript 100.00% (11/11) +github.com/btcsuite/btcscript/opcode.go opcodeMax 100.00% (10/10) +github.com/btcsuite/btcscript/opcode.go opcodeLessThan 100.00% (10/10) +github.com/btcsuite/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) +github.com/btcsuite/btcscript/log.go SetLogWriter 100.00% (10/10) github.com/btcsuite/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/btcsuite/btcscript/script.go PushedData 100.00% (10/10) -github.com/btcsuite/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) github.com/btcsuite/btcscript/opcode.go opcodeMin 100.00% (10/10) -github.com/btcsuite/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) +github.com/btcsuite/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) +github.com/btcsuite/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) github.com/btcsuite/btcscript/stack.go Stack.Tuck 100.00% (10/10) github.com/btcsuite/btcscript/script.go getSigOpCount 100.00% (10/10) -github.com/btcsuite/btcscript/log.go SetLogWriter 100.00% (10/10) +github.com/btcsuite/btcscript/script.go PushedData 100.00% (10/10) github.com/btcsuite/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) -github.com/btcsuite/btcscript/opcode.go opcodeMax 100.00% (10/10) -github.com/btcsuite/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) -github.com/btcsuite/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) -github.com/btcsuite/btcscript/opcode.go opcodeLessThan 100.00% (10/10) -github.com/btcsuite/btcscript/script.go DisasmString 100.00% (9/9) +github.com/btcsuite/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) +github.com/btcsuite/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) +github.com/btcsuite/btcscript/stack.go Stack.RotN 100.00% (9/9) +github.com/btcsuite/btcscript/script.go SignatureScript 100.00% (9/9) github.com/btcsuite/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/btcsuite/btcscript/stack.go Stack.SwapN 100.00% (9/9) -github.com/btcsuite/btcscript/script.go SignatureScript 100.00% (9/9) -github.com/btcsuite/btcscript/stack.go Stack.RotN 100.00% (9/9) +github.com/btcsuite/btcscript/script.go DisasmString 100.00% (9/9) github.com/btcsuite/btcscript/script.go Script.CheckErrorCondition 100.00% (9/9) github.com/btcsuite/btcscript/script.go Script.Execute 100.00% (8/8) -github.com/btcsuite/btcscript/opcode.go opcodeEqual 100.00% (8/8) -github.com/btcsuite/btcscript/script.go MultiSigScript 100.00% (8/8) +github.com/btcsuite/btcscript/stack.go Stack.DupN 100.00% (8/8) github.com/btcsuite/btcscript/script.go CalcMultiSigStats 100.00% (8/8) github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.AddOp 100.00% (8/8) github.com/btcsuite/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/btcsuite/btcscript/opcode.go opcodeSub 100.00% (8/8) -github.com/btcsuite/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/btcsuite/btcscript/opcode.go opcodeEqual 100.00% (8/8) +github.com/btcsuite/btcscript/script.go MultiSigScript 100.00% (8/8) +github.com/btcsuite/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) github.com/btcsuite/btcscript/opcode.go opcodeNot 100.00% (7/7) github.com/btcsuite/btcscript/stack.go Stack.DropN 100.00% (7/7) -github.com/btcsuite/btcscript/opcode.go opcodeNop 100.00% (7/7) -github.com/btcsuite/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) github.com/btcsuite/btcscript/script.go HasCanonicalPushes 100.00% (7/7) -github.com/btcsuite/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/btcsuite/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) -github.com/btcsuite/btcscript/opcode.go opcodeIfDup 100.00% (6/6) github.com/btcsuite/btcscript/opcode.go opcodeVerify 100.00% (6/6) +github.com/btcsuite/btcscript/opcode.go opcodeIfDup 100.00% (6/6) +github.com/btcsuite/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) +github.com/btcsuite/btcscript/opcode.go opcodeElse 100.00% (6/6) github.com/btcsuite/btcscript/opcode.go opcodeEndif 100.00% (6/6) github.com/btcsuite/btcscript/script.go removeOpcode 100.00% (5/5) github.com/btcsuite/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) @@ -83,87 +82,88 @@ github.com/btcsuite/btcscript/script.go Script.DisasmScript 100.00% (5/5) github.com/btcsuite/btcscript/script.go removeOpcodeByData 100.00% (5/5) github.com/btcsuite/btcscript/stack.go Stack.PickN 100.00% (5/5) github.com/btcsuite/btcscript/stack.go Stack.RollN 100.00% (5/5) -github.com/btcsuite/btcscript/script.go Script.curPC 100.00% (4/4) github.com/btcsuite/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) -github.com/btcsuite/btcscript/opcode.go opcodeCheckSigVerify 100.00% (4/4) -github.com/btcsuite/btcscript/opcode.go parsedOpcode.alwaysIllegal 100.00% (4/4) github.com/btcsuite/btcscript/script.go IsPayToScriptHash 100.00% (4/4) -github.com/btcsuite/btcscript/stack.go Stack.PeekBool 100.00% (4/4) github.com/btcsuite/btcscript/script.go isNullData 100.00% (4/4) -github.com/btcsuite/btcscript/stack.go Stack.PeekInt 100.00% (4/4) github.com/btcsuite/btcscript/script.go IsPushOnlyScript 100.00% (4/4) -github.com/btcsuite/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) -github.com/btcsuite/btcscript/stack.go Stack.PopBool 100.00% (4/4) -github.com/btcsuite/btcscript/script.go GetScriptClass 100.00% (4/4) github.com/btcsuite/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) -github.com/btcsuite/btcscript/stack.go Stack.PopInt 100.00% (4/4) +github.com/btcsuite/btcscript/script.go GetScriptClass 100.00% (4/4) github.com/btcsuite/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) -github.com/btcsuite/btcscript/stack.go asBool 100.00% (4/4) -github.com/btcsuite/btcscript/script.go getStack 100.00% (4/4) -github.com/btcsuite/btcscript/script.go @1338:17 100.00% (4/4) -github.com/btcsuite/btcscript/script.go isPushOnly 100.00% (4/4) github.com/btcsuite/btcscript/script.go Script.DisasmPC 100.00% (4/4) -github.com/btcsuite/btcscript/script.go ScriptClass.String 100.00% (3/3) -github.com/btcsuite/btcscript/script.go setStack 100.00% (3/3) -github.com/btcsuite/btcscript/script.go isSmallInt 100.00% (3/3) +github.com/btcsuite/btcscript/script.go isPushOnly 100.00% (4/4) +github.com/btcsuite/btcscript/script.go @1346:17 100.00% (4/4) +github.com/btcsuite/btcscript/script.go getStack 100.00% (4/4) +github.com/btcsuite/btcscript/script.go Script.curPC 100.00% (4/4) +github.com/btcsuite/btcscript/opcode.go opcodeNop 100.00% (4/4) +github.com/btcsuite/btcscript/stack.go asBool 100.00% (4/4) +github.com/btcsuite/btcscript/stack.go Stack.PopInt 100.00% (4/4) +github.com/btcsuite/btcscript/stack.go Stack.PopBool 100.00% (4/4) +github.com/btcsuite/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) +github.com/btcsuite/btcscript/stack.go Stack.PeekInt 100.00% (4/4) +github.com/btcsuite/btcscript/stack.go Stack.PeekBool 100.00% (4/4) +github.com/btcsuite/btcscript/opcode.go parsedOpcode.alwaysIllegal 100.00% (4/4) +github.com/btcsuite/btcscript/opcode.go opcodeCheckSigVerify 100.00% (4/4) github.com/btcsuite/btcscript/script.go asSmallInt 100.00% (3/3) -github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.AddFullData 100.00% (3/3) -github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.Reset 100.00% (3/3) +github.com/btcsuite/btcscript/script.go ScriptClass.String 100.00% (3/3) github.com/btcsuite/btcscript/stack.go fromBool 100.00% (3/3) -github.com/btcsuite/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/btcsuite/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/btcsuite/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/btcsuite/btcscript/opcode.go opcodeFalse 100.00% (2/2) -github.com/btcsuite/btcscript/opcode.go opcodePushData 100.00% (2/2) -github.com/btcsuite/btcscript/opcode.go opcode1Negate 100.00% (2/2) -github.com/btcsuite/btcscript/script.go GetSigOpCount 100.00% (2/2) -github.com/btcsuite/btcscript/stack.go Stack.Depth 100.00% (2/2) -github.com/btcsuite/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.Reset 100.00% (3/3) +github.com/btcsuite/btcscript/script.go isSmallInt 100.00% (3/3) +github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.AddFullData 100.00% (3/3) +github.com/btcsuite/btcscript/script.go setStack 100.00% (3/3) github.com/btcsuite/btcscript/opcode.go opcodeN 100.00% (2/2) -github.com/btcsuite/btcscript/script.go Script.SetAltStack 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcodeDrop 100.00% (1/1) -github.com/btcsuite/btcscript/script.go payToPubKeyHashScript 100.00% (1/1) -github.com/btcsuite/btcscript/script.go payToScriptHashScript 100.00% (1/1) -github.com/btcsuite/btcscript/script.go payToPubKeyScript 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcode2Swap 100.00% (1/1) +github.com/btcsuite/btcscript/stack.go Stack.Depth 100.00% (2/2) +github.com/btcsuite/btcscript/opcode.go calcHash 100.00% (2/2) +github.com/btcsuite/btcscript/opcode.go opcode1Negate 100.00% (2/2) +github.com/btcsuite/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/btcsuite/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/btcsuite/btcscript/script.go GetSigOpCount 100.00% (2/2) +github.com/btcsuite/btcscript/opcode.go opcodeFalse 100.00% (2/2) +github.com/btcsuite/btcscript/opcode.go opcodeDepth 100.00% (2/2) +github.com/btcsuite/btcscript/opcode.go opcodePushData 100.00% (2/2) github.com/btcsuite/btcscript/opcode.go opcode2Rot 100.00% (1/1) github.com/btcsuite/btcscript/opcode.go opcode2Over 100.00% (1/1) -github.com/btcsuite/btcscript/scriptbuilder.go ErrScriptNotCanonical.Error 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcode3Dup 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go init 100.00% (1/1) github.com/btcsuite/btcscript/script.go KeyClosure.GetKey 100.00% (1/1) github.com/btcsuite/btcscript/script.go ScriptClosure.GetScript 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcode2Dup 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcodeOver 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcodeNip 100.00% (1/1) +github.com/btcsuite/btcscript/log.go DisableLog 100.00% (1/1) +github.com/btcsuite/btcscript/log.go init 100.00% (1/1) github.com/btcsuite/btcscript/script.go Script.disasm 100.00% (1/1) github.com/btcsuite/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcodeSwap 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcodeNip 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcode2Drop 100.00% (1/1) github.com/btcsuite/btcscript/opcode.go opcodeDup 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcodeTuck 100.00% (1/1) -github.com/btcsuite/btcscript/log.go UseLogger 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcodeDrop 100.00% (1/1) github.com/btcsuite/btcscript/script.go Script.GetStack 100.00% (1/1) github.com/btcsuite/btcscript/script.go Script.SetStack 100.00% (1/1) github.com/btcsuite/btcscript/script.go Script.GetAltStack 100.00% (1/1) +github.com/btcsuite/btcscript/script.go Script.SetAltStack 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcode2Swap 100.00% (1/1) +github.com/btcsuite/btcscript/script.go payToPubKeyHashScript 100.00% (1/1) +github.com/btcsuite/btcscript/script.go payToScriptHashScript 100.00% (1/1) +github.com/btcsuite/btcscript/script.go payToPubKeyScript 100.00% (1/1) github.com/btcsuite/btcscript/opcode.go opcodeInvalid 100.00% (1/1) -github.com/btcsuite/btcscript/script.go isPubkey 100.00% (1/1) +github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) github.com/btcsuite/btcscript/scriptbuilder.go NewScriptBuilder 100.00% (1/1) github.com/btcsuite/btcscript/opcode.go opcodeReserved 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcode2Dup 100.00% (1/1) -github.com/btcsuite/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) -github.com/btcsuite/btcscript/stack.go Stack.PushInt 100.00% (1/1) -github.com/btcsuite/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) -github.com/btcsuite/btcscript/script.go parseScript 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go calcHash160 100.00% (1/1) -github.com/btcsuite/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go init 100.00% (1/1) github.com/btcsuite/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcodeOver 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcodeRot 100.00% (1/1) -github.com/btcsuite/btcscript/log.go DisableLog 100.00% (1/1) -github.com/btcsuite/btcscript/log.go init 100.00% (1/1) -github.com/btcsuite/btcscript/stack.go Stack.PushBool 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcode3Dup 100.00% (1/1) +github.com/btcsuite/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) github.com/btcsuite/btcscript/script.go isPubkeyHash 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcode2Drop 100.00% (1/1) -github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) +github.com/btcsuite/btcscript/script.go isScriptHash 100.00% (1/1) +github.com/btcsuite/btcscript/stack.go Stack.PushInt 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/btcsuite/btcscript/stack.go Stack.PushBool 100.00% (1/1) +github.com/btcsuite/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) +github.com/btcsuite/btcscript/script.go isPubkey 100.00% (1/1) +github.com/btcsuite/btcscript/log.go UseLogger 100.00% (1/1) +github.com/btcsuite/btcscript/script.go parseScript 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcodeTuck 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcodeSwap 100.00% (1/1) +github.com/btcsuite/btcscript/opcode.go opcodeRot 100.00% (1/1) github.com/btcsuite/btcscript/opcode.go opcodeReturn 100.00% (1/1) +github.com/btcsuite/btcscript/scriptbuilder.go ErrScriptNotCanonical.Error 100.00% (1/1) github.com/btcsuite/btcscript/opcode.go opcodeCheckMultiSig 98.48% (65/66) github.com/btcsuite/btcscript/script.go mergeScripts 95.24% (20/21) github.com/btcsuite/btcscript/script.go signMultiSig 93.33% (14/15) @@ -175,12 +175,12 @@ github.com/btcsuite/btcscript/script.go unparseScript 85.71% (6/7) github.com/btcsuite/btcscript/script.go SignTxOutput 80.00% (12/15) github.com/btcsuite/btcscript/script.go p2pkSignatureScript 75.00% (3/4) github.com/btcsuite/btcscript/script.go sign 69.23% (18/26) -github.com/btcsuite/btcscript/script.go @598:34 0.00% (0/6) -github.com/btcsuite/btcscript/script.go @586:34 0.00% (0/4) +github.com/btcsuite/btcscript/script.go @606:34 0.00% (0/6) +github.com/btcsuite/btcscript/script.go @594:34 0.00% (0/4) github.com/btcsuite/btcscript/stack.go Stack.String 0.00% (0/4) -github.com/btcsuite/btcscript/script.go @631:34 0.00% (0/3) -github.com/btcsuite/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/btcsuite/btcscript/opcode.go @1815:33 0.00% (0/1) +github.com/btcsuite/btcscript/script.go @639:34 0.00% (0/3) github.com/btcsuite/btcscript/opcode.go opcodeDisabled 0.00% (0/1) -github.com/btcsuite/btcscript --------------------------- 96.69% (1285/1329) +github.com/btcsuite/btcscript/log.go logClosure.String 0.00% (0/1) +github.com/btcsuite/btcscript/opcode.go @1810:33 0.00% (0/1) +github.com/btcsuite/btcscript --------------------------- 96.69% (1284/1328) From cbda0648425e58c2bf0db97f5dd7a74da7accf5e Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 30 Jan 2015 00:03:01 -0600 Subject: [PATCH 174/174] Import btcscript repo into txscript directory. This commit contains the entire btcscript repository along with several changes needed to move all of the files into the txscript directory in order to prepare it for merging. This does NOT update btcd or any of the other packages to use the new location as that will be done separately. - All import paths in the old btcscript test files have been changed to the new location - All references to btcscript as the package name have been chagned to txscript This is ongoing work toward #214. --- .gitignore | 28 - .travis.yml | 3 - LICENSE | 13 - cov_report.sh | 17 - test_coverage.txt | 186 -- README.md => txscript/README.md | 43 +- address.go => txscript/address.go | 4 +- address_test.go => txscript/address_test.go | 46 +- {data => txscript/data}/LICENSE | 0 {data => txscript/data}/script_invalid.json | 0 {data => txscript/data}/script_valid.json | 0 {data => txscript/data}/tx_invalid.json | 0 {data => txscript/data}/tx_valid.json | 0 doc.go => txscript/doc.go | 8 +- example_test.go => txscript/example_test.go | 12 +- internal_test.go => txscript/internal_test.go | 4 +- log.go => txscript/log.go | 4 +- log_test.go => txscript/log_test.go | 8 +- opcode.go => txscript/opcode.go | 6 +- opcode_test.go => txscript/opcode_test.go | 2764 ++++++++--------- script.go => txscript/script.go | 6 +- script_test.go => txscript/script_test.go | 1116 +++---- scriptbuilder.go => txscript/scriptbuilder.go | 12 +- .../scriptbuilder_test.go | 246 +- stack.go => txscript/stack.go | 4 +- stack_test.go => txscript/stack_test.go | 210 +- 26 files changed, 2242 insertions(+), 2498 deletions(-) delete mode 100644 .gitignore delete mode 100644 .travis.yml delete mode 100644 LICENSE delete mode 100644 cov_report.sh delete mode 100644 test_coverage.txt rename README.md => txscript/README.md (53%) rename address.go => txscript/address.go (97%) rename address_test.go => txscript/address_test.go (93%) rename {data => txscript/data}/LICENSE (100%) rename {data => txscript/data}/script_invalid.json (100%) rename {data => txscript/data}/script_valid.json (100%) rename {data => txscript/data}/tx_invalid.json (100%) rename {data => txscript/data}/tx_valid.json (100%) rename doc.go => txscript/doc.go (87%) rename example_test.go => txscript/example_test.go (87%) rename internal_test.go => txscript/internal_test.go (99%) rename log.go => txscript/log.go (96%) rename log_test.go => txscript/log_test.go (88%) rename opcode.go => txscript/opcode.go (99%) rename opcode_test.go => txscript/opcode_test.go (64%) rename script.go => txscript/script.go (99%) rename script_test.go => txscript/script_test.go (83%) rename scriptbuilder.go => txscript/scriptbuilder.go (97%) rename scriptbuilder_test.go => txscript/scriptbuilder_test.go (61%) rename stack.go => txscript/stack.go (99%) rename stack_test.go => txscript/stack_test.go (78%) diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 5b97dbba..00000000 --- a/.gitignore +++ /dev/null @@ -1,28 +0,0 @@ -# Temp files -*~ - -# Log files -*.log - -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index ae71c02f..00000000 --- a/.travis.yml +++ /dev/null @@ -1,3 +0,0 @@ -language: go -go: release -install: go get -d -t -v ./... diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 67cfe82f..00000000 --- a/LICENSE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright (c) 2013-2014 Conformal Systems LLC. - -Permission to use, copy, modify, and distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/cov_report.sh b/cov_report.sh deleted file mode 100644 index 307f05b7..00000000 --- a/cov_report.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh - -# This script uses gocov to generate a test coverage report. -# The gocov tool my be obtained with the following command: -# go get github.com/axw/gocov/gocov -# -# It will be installed to $GOPATH/bin, so ensure that location is in your $PATH. - -# Check for gocov. -type gocov >/dev/null 2>&1 -if [ $? -ne 0 ]; then - echo >&2 "This script requires the gocov tool." - echo >&2 "You may obtain it with the following command:" - echo >&2 "go get github.com/axw/gocov/gocov" - exit 1 -fi -gocov test | gocov report diff --git a/test_coverage.txt b/test_coverage.txt deleted file mode 100644 index 972b97c8..00000000 --- a/test_coverage.txt +++ /dev/null @@ -1,186 +0,0 @@ - -github.com/btcsuite/btcscript/script.go calcScriptHash 100.00% (39/39) -github.com/btcsuite/btcscript/script.go Script.Step 100.00% (37/37) -github.com/btcsuite/btcscript/opcode.go opcodeCheckSig 100.00% (29/29) -github.com/btcsuite/btcscript/script.go parseScriptTemplate 100.00% (29/29) -github.com/btcsuite/btcscript/script.go NewScript 100.00% (29/29) -github.com/btcsuite/btcscript/address.go ExtractPkScriptAddrs 100.00% (27/27) -github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.addData 100.00% (25/25) -github.com/btcsuite/btcscript/script.go CalcScriptInfo 100.00% (25/25) -github.com/btcsuite/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23) -github.com/btcsuite/btcscript/stack.go asInt 100.00% (23/23) -github.com/btcsuite/btcscript/opcode.go parsedOpcode.disabled 100.00% (17/17) -github.com/btcsuite/btcscript/opcode.go parsedOpcode.print 100.00% (16/16) -github.com/btcsuite/btcscript/stack.go Stack.nipN 100.00% (15/15) -github.com/btcsuite/btcscript/scriptbuilder.go canonicalDataSize 100.00% (14/14) -github.com/btcsuite/btcscript/stack.go fromInt 100.00% (14/14) -github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.AddUint64 100.00% (13/13) -github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.AddData 100.00% (13/13) -github.com/btcsuite/btcscript/script.go isMultiSig 100.00% (13/13) -github.com/btcsuite/btcscript/opcode.go opcodeWithin 100.00% (13/13) -github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.AddInt64 100.00% (13/13) -github.com/btcsuite/btcscript/opcode.go parsedOpcode.exec 100.00% (13/13) -github.com/btcsuite/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13) -github.com/btcsuite/btcscript/opcode.go opcodeIf 100.00% (11/11) -github.com/btcsuite/btcscript/opcode.go opcodeNotIf 100.00% (11/11) -github.com/btcsuite/btcscript/script.go PayToAddrScript 100.00% (11/11) -github.com/btcsuite/btcscript/script.go typeOfScript 100.00% (11/11) -github.com/btcsuite/btcscript/opcode.go opcodeMax 100.00% (10/10) -github.com/btcsuite/btcscript/opcode.go opcodeLessThan 100.00% (10/10) -github.com/btcsuite/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) -github.com/btcsuite/btcscript/log.go SetLogWriter 100.00% (10/10) -github.com/btcsuite/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/btcsuite/btcscript/opcode.go opcodeMin 100.00% (10/10) -github.com/btcsuite/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) -github.com/btcsuite/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) -github.com/btcsuite/btcscript/stack.go Stack.Tuck 100.00% (10/10) -github.com/btcsuite/btcscript/script.go getSigOpCount 100.00% (10/10) -github.com/btcsuite/btcscript/script.go PushedData 100.00% (10/10) -github.com/btcsuite/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) -github.com/btcsuite/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) -github.com/btcsuite/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) -github.com/btcsuite/btcscript/stack.go Stack.RotN 100.00% (9/9) -github.com/btcsuite/btcscript/script.go SignatureScript 100.00% (9/9) -github.com/btcsuite/btcscript/stack.go Stack.OverN 100.00% (9/9) -github.com/btcsuite/btcscript/stack.go Stack.SwapN 100.00% (9/9) -github.com/btcsuite/btcscript/script.go DisasmString 100.00% (9/9) -github.com/btcsuite/btcscript/script.go Script.CheckErrorCondition 100.00% (9/9) -github.com/btcsuite/btcscript/script.go Script.Execute 100.00% (8/8) -github.com/btcsuite/btcscript/stack.go Stack.DupN 100.00% (8/8) -github.com/btcsuite/btcscript/script.go CalcMultiSigStats 100.00% (8/8) -github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.AddOp 100.00% (8/8) -github.com/btcsuite/btcscript/opcode.go opcodeAdd 100.00% (8/8) -github.com/btcsuite/btcscript/opcode.go opcodeSub 100.00% (8/8) -github.com/btcsuite/btcscript/opcode.go opcodeEqual 100.00% (8/8) -github.com/btcsuite/btcscript/script.go MultiSigScript 100.00% (8/8) -github.com/btcsuite/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) -github.com/btcsuite/btcscript/opcode.go opcodeNot 100.00% (7/7) -github.com/btcsuite/btcscript/stack.go Stack.DropN 100.00% (7/7) -github.com/btcsuite/btcscript/script.go HasCanonicalPushes 100.00% (7/7) -github.com/btcsuite/btcscript/opcode.go opcodeVerify 100.00% (6/6) -github.com/btcsuite/btcscript/opcode.go opcodeIfDup 100.00% (6/6) -github.com/btcsuite/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) -github.com/btcsuite/btcscript/opcode.go opcodeElse 100.00% (6/6) -github.com/btcsuite/btcscript/opcode.go opcodeEndif 100.00% (6/6) -github.com/btcsuite/btcscript/script.go removeOpcode 100.00% (5/5) -github.com/btcsuite/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) -github.com/btcsuite/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) -github.com/btcsuite/btcscript/opcode.go opcodePick 100.00% (5/5) -github.com/btcsuite/btcscript/opcode.go opcodeRoll 100.00% (5/5) -github.com/btcsuite/btcscript/opcode.go opcodeSize 100.00% (5/5) -github.com/btcsuite/btcscript/opcode.go opcode1Add 100.00% (5/5) -github.com/btcsuite/btcscript/opcode.go opcode1Sub 100.00% (5/5) -github.com/btcsuite/btcscript/opcode.go opcodeNegate 100.00% (5/5) -github.com/btcsuite/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/btcsuite/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) -github.com/btcsuite/btcscript/opcode.go opcodeSha1 100.00% (5/5) -github.com/btcsuite/btcscript/opcode.go opcodeSha256 100.00% (5/5) -github.com/btcsuite/btcscript/opcode.go opcodeHash160 100.00% (5/5) -github.com/btcsuite/btcscript/opcode.go opcodeHash256 100.00% (5/5) -github.com/btcsuite/btcscript/script.go Script.validPC 100.00% (5/5) -github.com/btcsuite/btcscript/script.go Script.DisasmScript 100.00% (5/5) -github.com/btcsuite/btcscript/script.go removeOpcodeByData 100.00% (5/5) -github.com/btcsuite/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/btcsuite/btcscript/stack.go Stack.RollN 100.00% (5/5) -github.com/btcsuite/btcscript/opcode.go opcodeCheckMultiSigVerify 100.00% (4/4) -github.com/btcsuite/btcscript/script.go IsPayToScriptHash 100.00% (4/4) -github.com/btcsuite/btcscript/script.go isNullData 100.00% (4/4) -github.com/btcsuite/btcscript/script.go IsPushOnlyScript 100.00% (4/4) -github.com/btcsuite/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) -github.com/btcsuite/btcscript/script.go GetScriptClass 100.00% (4/4) -github.com/btcsuite/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) -github.com/btcsuite/btcscript/script.go Script.DisasmPC 100.00% (4/4) -github.com/btcsuite/btcscript/script.go isPushOnly 100.00% (4/4) -github.com/btcsuite/btcscript/script.go @1346:17 100.00% (4/4) -github.com/btcsuite/btcscript/script.go getStack 100.00% (4/4) -github.com/btcsuite/btcscript/script.go Script.curPC 100.00% (4/4) -github.com/btcsuite/btcscript/opcode.go opcodeNop 100.00% (4/4) -github.com/btcsuite/btcscript/stack.go asBool 100.00% (4/4) -github.com/btcsuite/btcscript/stack.go Stack.PopInt 100.00% (4/4) -github.com/btcsuite/btcscript/stack.go Stack.PopBool 100.00% (4/4) -github.com/btcsuite/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) -github.com/btcsuite/btcscript/stack.go Stack.PeekInt 100.00% (4/4) -github.com/btcsuite/btcscript/stack.go Stack.PeekBool 100.00% (4/4) -github.com/btcsuite/btcscript/opcode.go parsedOpcode.alwaysIllegal 100.00% (4/4) -github.com/btcsuite/btcscript/opcode.go opcodeCheckSigVerify 100.00% (4/4) -github.com/btcsuite/btcscript/script.go asSmallInt 100.00% (3/3) -github.com/btcsuite/btcscript/script.go ScriptClass.String 100.00% (3/3) -github.com/btcsuite/btcscript/stack.go fromBool 100.00% (3/3) -github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.Reset 100.00% (3/3) -github.com/btcsuite/btcscript/script.go isSmallInt 100.00% (3/3) -github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.AddFullData 100.00% (3/3) -github.com/btcsuite/btcscript/script.go setStack 100.00% (3/3) -github.com/btcsuite/btcscript/opcode.go opcodeN 100.00% (2/2) -github.com/btcsuite/btcscript/stack.go Stack.Depth 100.00% (2/2) -github.com/btcsuite/btcscript/opcode.go calcHash 100.00% (2/2) -github.com/btcsuite/btcscript/opcode.go opcode1Negate 100.00% (2/2) -github.com/btcsuite/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) -github.com/btcsuite/btcscript/stack.go Stack.NipN 100.00% (2/2) -github.com/btcsuite/btcscript/script.go GetSigOpCount 100.00% (2/2) -github.com/btcsuite/btcscript/opcode.go opcodeFalse 100.00% (2/2) -github.com/btcsuite/btcscript/opcode.go opcodeDepth 100.00% (2/2) -github.com/btcsuite/btcscript/opcode.go opcodePushData 100.00% (2/2) -github.com/btcsuite/btcscript/opcode.go opcode2Rot 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcode2Over 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcode3Dup 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go init 100.00% (1/1) -github.com/btcsuite/btcscript/script.go KeyClosure.GetKey 100.00% (1/1) -github.com/btcsuite/btcscript/script.go ScriptClosure.GetScript 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcode2Dup 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcodeOver 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcodeNip 100.00% (1/1) -github.com/btcsuite/btcscript/log.go DisableLog 100.00% (1/1) -github.com/btcsuite/btcscript/log.go init 100.00% (1/1) -github.com/btcsuite/btcscript/script.go Script.disasm 100.00% (1/1) -github.com/btcsuite/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcode2Drop 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcodeDup 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcodeDrop 100.00% (1/1) -github.com/btcsuite/btcscript/script.go Script.GetStack 100.00% (1/1) -github.com/btcsuite/btcscript/script.go Script.SetStack 100.00% (1/1) -github.com/btcsuite/btcscript/script.go Script.GetAltStack 100.00% (1/1) -github.com/btcsuite/btcscript/script.go Script.SetAltStack 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcode2Swap 100.00% (1/1) -github.com/btcsuite/btcscript/script.go payToPubKeyHashScript 100.00% (1/1) -github.com/btcsuite/btcscript/script.go payToScriptHashScript 100.00% (1/1) -github.com/btcsuite/btcscript/script.go payToPubKeyScript 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcodeInvalid 100.00% (1/1) -github.com/btcsuite/btcscript/scriptbuilder.go ScriptBuilder.Script 100.00% (1/1) -github.com/btcsuite/btcscript/scriptbuilder.go NewScriptBuilder 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcodeReserved 100.00% (1/1) -github.com/btcsuite/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/btcsuite/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) -github.com/btcsuite/btcscript/script.go isPubkeyHash 100.00% (1/1) -github.com/btcsuite/btcscript/script.go isScriptHash 100.00% (1/1) -github.com/btcsuite/btcscript/stack.go Stack.PushInt 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go calcHash160 100.00% (1/1) -github.com/btcsuite/btcscript/stack.go Stack.PushBool 100.00% (1/1) -github.com/btcsuite/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) -github.com/btcsuite/btcscript/script.go isPubkey 100.00% (1/1) -github.com/btcsuite/btcscript/log.go UseLogger 100.00% (1/1) -github.com/btcsuite/btcscript/script.go parseScript 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcodeTuck 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcodeSwap 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcodeRot 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/btcsuite/btcscript/scriptbuilder.go ErrScriptNotCanonical.Error 100.00% (1/1) -github.com/btcsuite/btcscript/opcode.go opcodeCheckMultiSig 98.48% (65/66) -github.com/btcsuite/btcscript/script.go mergeScripts 95.24% (20/21) -github.com/btcsuite/btcscript/script.go signMultiSig 93.33% (14/15) -github.com/btcsuite/btcscript/script.go canonicalPush 92.86% (13/14) -github.com/btcsuite/btcscript/script.go mergeMultiSig 88.37% (38/43) -github.com/btcsuite/btcscript/script.go RawTxInSignature 87.50% (7/8) -github.com/btcsuite/btcscript/script.go expectedInputs 85.71% (6/7) -github.com/btcsuite/btcscript/script.go unparseScript 85.71% (6/7) -github.com/btcsuite/btcscript/script.go SignTxOutput 80.00% (12/15) -github.com/btcsuite/btcscript/script.go p2pkSignatureScript 75.00% (3/4) -github.com/btcsuite/btcscript/script.go sign 69.23% (18/26) -github.com/btcsuite/btcscript/script.go @606:34 0.00% (0/6) -github.com/btcsuite/btcscript/script.go @594:34 0.00% (0/4) -github.com/btcsuite/btcscript/stack.go Stack.String 0.00% (0/4) -github.com/btcsuite/btcscript/script.go @639:34 0.00% (0/3) -github.com/btcsuite/btcscript/opcode.go opcodeDisabled 0.00% (0/1) -github.com/btcsuite/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/btcsuite/btcscript/opcode.go @1810:33 0.00% (0/1) -github.com/btcsuite/btcscript --------------------------- 96.69% (1284/1328) - diff --git a/README.md b/txscript/README.md similarity index 53% rename from README.md rename to txscript/README.md index 35340507..96fce144 100644 --- a/README.md +++ b/txscript/README.md @@ -1,20 +1,15 @@ -btcscript -========= +txscript +======== -[![Build Status](https://travis-ci.org/btcsuite/btcscript.png?branch=master)] -(https://travis-ci.org/btcsuite/btcscript) +[![Build Status](https://travis-ci.org/btcsuite/btcd.png?branch=master)] +(https://travis-ci.org/btcsuite/btcd) -Package btcscript implements the bitcoin transaction scripts. There is -a comprehensive test suite. `test_coverage.txt` contains the current -coverage statistics (generated using gocov). On a UNIX-like OS, the -script `cov_report.sh` can be used to generate the report. Package -btcscript is licensed under the liberal ISC license. +Package txscript implements the bitcoin transaction script language. There is +a comprehensive test suite. Package txscript is licensed under the liberal ISC +license. -This package is one of the core packages from btcd, an alternative full-node -implementation of bitcoin which is under active development by Conformal. -Although it was primarily written for btcd, this package has intentionally been -designed so it can be used as a standalone package for any projects needing to -use or validate bitcoin transaction scripts. +This package has intentionally been designed so it can be used as a standalone +package for any projects needing to use or validate bitcoin transaction scripts. ## Bitcoin Scripts @@ -25,39 +20,35 @@ can be found at https://en.bitcoin.it/wiki/Script ## Documentation -[![GoDoc](https://godoc.org/github.com/btcsuite/btcscript?status.png)] -(http://godoc.org/github.com/btcsuite/btcscript) +[![GoDoc](https://godoc.org/github.com/btcsuite/btcd/txscript?status.png)] +(http://godoc.org/github.com/btcsuite/btcd/txscript) Full `go doc` style documentation for the project can be viewed online without installing this package by using the GoDoc site -[here](http://godoc.org/github.com/btcsuite/btcscript). +[here](http://godoc.org/github.com/btcsuite/btcd/txscript). You can also view the documentation locally once the package is installed with the `godoc` tool by running `godoc -http=":6060"` and pointing your browser to -http://localhost:6060/pkg/github.com/btcsuite/btcscript +http://localhost:6060/pkg/github.com/btcsuite/btcd/txscript ## Installation ```bash -$ go get github.com/btcsuite/btcscript +$ go get github.com/btcsuite/btcd/txscript ``` ## Examples * [Standard Pay-to-pubkey-hash Script] - (http://godoc.org/github.com/btcsuite/btcscript#example-PayToAddrScript) + (http://godoc.org/github.com/btcsuite/btcd/txscript#example-PayToAddrScript) Demonstrates creating a script which pays to a bitcoin address. It also prints the created script hex and uses the DisasmString function to display the disassembled script. * [Extracting Details from Standard Scripts] - (http://godoc.org/github.com/btcsuite/btcscript#example-ExtractPkScriptAddrs) + (http://godoc.org/github.com/btcsuite/btcd/txscript#example-ExtractPkScriptAddrs) Demonstrates extracting information from a standard public key script. -## TODO - -- Increase test coverage to 100% - ## GPG Verification Key All official release tags are signed by Conformal so users can ensure the code @@ -80,4 +71,4 @@ signature perform the following: ## License -Package btcscript is licensed under the liberal ISC License. +Package txscript is licensed under the liberal ISC License. diff --git a/address.go b/txscript/address.go similarity index 97% rename from address.go rename to txscript/address.go index 7f6b9872..cfa5dd09 100644 --- a/address.go +++ b/txscript/address.go @@ -1,8 +1,8 @@ -// Copyright (c) 2013-2014 Conformal Systems LLC. +// Copyright (c) 2013-2015 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. -package btcscript +package txscript import ( "github.com/btcsuite/btcnet" diff --git a/address_test.go b/txscript/address_test.go similarity index 93% rename from address_test.go rename to txscript/address_test.go index 36598e88..9345e7d7 100644 --- a/address_test.go +++ b/txscript/address_test.go @@ -1,15 +1,15 @@ -// Copyright (c) 2013-2014 Conformal Systems LLC. +// Copyright (c) 2013-2015 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. -package btcscript_test +package txscript_test import ( "encoding/hex" "reflect" "testing" + "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcnet" - "github.com/btcsuite/btcscript" "github.com/btcsuite/btcutil" ) @@ -75,7 +75,7 @@ func TestExtractPkScriptAddrs(t *testing.T) { script []byte addrs []btcutil.Address reqSigs int - class btcscript.ScriptClass + class txscript.ScriptClass }{ { name: "standard p2pk with compressed pubkey (0x02)", @@ -87,7 +87,7 @@ func TestExtractPkScriptAddrs(t *testing.T) { "4895dca52c6b4")), }, reqSigs: 1, - class: btcscript.PubKeyTy, + class: txscript.PubKeyTy, }, { name: "standard p2pk with uncompressed pubkey (0x04)", @@ -103,7 +103,7 @@ func TestExtractPkScriptAddrs(t *testing.T) { "412a3")), }, reqSigs: 1, - class: btcscript.PubKeyTy, + class: txscript.PubKeyTy, }, { name: "standard p2pk with hybrid pubkey (0x06)", @@ -119,7 +119,7 @@ func TestExtractPkScriptAddrs(t *testing.T) { "f453e")), }, reqSigs: 1, - class: btcscript.PubKeyTy, + class: txscript.PubKeyTy, }, { name: "standard p2pk with compressed pubkey (0x03)", @@ -131,7 +131,7 @@ func TestExtractPkScriptAddrs(t *testing.T) { "409273eb16e65")), }, reqSigs: 1, - class: btcscript.PubKeyTy, + class: txscript.PubKeyTy, }, { name: "2nd standard p2pk with uncompressed pubkey (0x04)", @@ -147,7 +147,7 @@ func TestExtractPkScriptAddrs(t *testing.T) { "8ef7b")), }, reqSigs: 1, - class: btcscript.PubKeyTy, + class: txscript.PubKeyTy, }, { name: "standard p2pk with hybrid pubkey (0x07)", @@ -163,7 +163,7 @@ func TestExtractPkScriptAddrs(t *testing.T) { "8ef7b")), }, reqSigs: 1, - class: btcscript.PubKeyTy, + class: txscript.PubKeyTy, }, { name: "standard p2pkh", @@ -174,7 +174,7 @@ func TestExtractPkScriptAddrs(t *testing.T) { "cbca9a9e3713bd7587509a30564")), }, reqSigs: 1, - class: btcscript.PubKeyHashTy, + class: txscript.PubKeyHashTy, }, { name: "standard p2sh", @@ -185,7 +185,7 @@ func TestExtractPkScriptAddrs(t *testing.T) { "ee0189dd5cc67f1b0e5f02f45cb")), }, reqSigs: 1, - class: btcscript.ScriptHashTy, + class: txscript.ScriptHashTy, }, // from real tx 60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1, vout 0 { @@ -210,7 +210,7 @@ func TestExtractPkScriptAddrs(t *testing.T) { "342af")), }, reqSigs: 1, - class: btcscript.MultiSigTy, + class: txscript.MultiSigTy, }, // from real tx d646f82bd5fbdb94a36872ce460f97662b80c3050ad3209bef9d1e398ea277ab, vin 1 { @@ -243,7 +243,7 @@ func TestExtractPkScriptAddrs(t *testing.T) { "0421a")), }, reqSigs: 2, - class: btcscript.MultiSigTy, + class: txscript.MultiSigTy, }, // The below are nonstandard script due to things such as @@ -258,7 +258,7 @@ func TestExtractPkScriptAddrs(t *testing.T) { "f656b412a3"), addrs: nil, reqSigs: 0, - class: btcscript.NonStandardTy, + class: txscript.NonStandardTy, }, { name: "valid signature from a sigscript - no addresses", @@ -268,7 +268,7 @@ func TestExtractPkScriptAddrs(t *testing.T) { "4622082221a8768d1d0901"), addrs: nil, reqSigs: 0, - class: btcscript.NonStandardTy, + class: txscript.NonStandardTy, }, // Note the technically the pubkey is the second item on the // stack, but since the address extraction intentionally only @@ -285,7 +285,7 @@ func TestExtractPkScriptAddrs(t *testing.T) { "a75a71042d40388a4d307f887d"), addrs: nil, reqSigs: 0, - class: btcscript.NonStandardTy, + class: txscript.NonStandardTy, }, // from real tx 691dd277dc0e90a462a3d652a1171686de49cf19067cd33c7df0392833fb986a, vout 0 // invalid public keys @@ -303,7 +303,7 @@ func TestExtractPkScriptAddrs(t *testing.T) { "35616463636453ae"), addrs: []btcutil.Address{}, reqSigs: 1, - class: btcscript.MultiSigTy, + class: txscript.MultiSigTy, }, // from real tx: 691dd277dc0e90a462a3d652a1171686de49cf19067cd33c7df0392833fb986a, vout 44 // invalid public keys @@ -319,27 +319,27 @@ func TestExtractPkScriptAddrs(t *testing.T) { "38613663663530616234636434340a00000053ae"), addrs: []btcutil.Address{}, reqSigs: 1, - class: btcscript.MultiSigTy, + class: txscript.MultiSigTy, }, { name: "empty script", script: []byte{}, addrs: nil, reqSigs: 0, - class: btcscript.NonStandardTy, + class: txscript.NonStandardTy, }, { name: "script that does not parse", - script: []byte{btcscript.OP_DATA_45}, + script: []byte{txscript.OP_DATA_45}, addrs: nil, reqSigs: 0, - class: btcscript.NonStandardTy, + class: txscript.NonStandardTy, }, } t.Logf("Running %d tests.", len(tests)) for i, test := range tests { - class, addrs, reqSigs, err := btcscript.ExtractPkScriptAddrs( + class, addrs, reqSigs, err := txscript.ExtractPkScriptAddrs( test.script, &btcnet.MainNetParams) if err != nil { } diff --git a/data/LICENSE b/txscript/data/LICENSE similarity index 100% rename from data/LICENSE rename to txscript/data/LICENSE diff --git a/data/script_invalid.json b/txscript/data/script_invalid.json similarity index 100% rename from data/script_invalid.json rename to txscript/data/script_invalid.json diff --git a/data/script_valid.json b/txscript/data/script_valid.json similarity index 100% rename from data/script_valid.json rename to txscript/data/script_valid.json diff --git a/data/tx_invalid.json b/txscript/data/tx_invalid.json similarity index 100% rename from data/tx_invalid.json rename to txscript/data/tx_invalid.json diff --git a/data/tx_valid.json b/txscript/data/tx_valid.json similarity index 100% rename from data/tx_valid.json rename to txscript/data/tx_valid.json diff --git a/doc.go b/txscript/doc.go similarity index 87% rename from doc.go rename to txscript/doc.go index 64d9e095..dfd1f2f2 100644 --- a/doc.go +++ b/txscript/doc.go @@ -1,9 +1,9 @@ -// Copyright (c) 2013-2014 Conformal Systems LLC. +// Copyright (c) 2013-2015 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. /* -Package btcscript implements bitcoin transaction scripts. +Package txscript implements the bitcoin transaction script language. A complete description of the script language used by bitcoin can be found at https://en.bitcoin.it/wiki/Script. The following only serves as a quick @@ -32,8 +32,8 @@ what conditions must be met in order to spend bitcoins. Errors -Errors returned by this package are of the form btcscript.ErrStackX where X +Errors returned by this package are of the form txscript.ErrStackX where X indicates the specific error. See Variables in the package documentation for a full list. */ -package btcscript +package txscript diff --git a/example_test.go b/txscript/example_test.go similarity index 87% rename from example_test.go rename to txscript/example_test.go index a798e288..4317ef5c 100644 --- a/example_test.go +++ b/txscript/example_test.go @@ -1,15 +1,15 @@ -// Copyright (c) 2014 Conformal Systems LLC. +// Copyright (c) 2014-2015 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. -package btcscript_test +package txscript_test import ( "encoding/hex" "fmt" + "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcnet" - "github.com/btcsuite/btcscript" "github.com/btcsuite/btcutil" ) @@ -29,14 +29,14 @@ func ExamplePayToAddrScript() { } // Create a public key script that pays to the address. - script, err := btcscript.PayToAddrScript(address) + script, err := txscript.PayToAddrScript(address) if err != nil { fmt.Println(err) return } fmt.Printf("Script Hex: %x\n", script) - disasm, err := btcscript.DisasmString(script) + disasm, err := txscript.DisasmString(script) if err != nil { fmt.Println(err) return @@ -60,7 +60,7 @@ func ExampleExtractPkScriptAddrs() { } // Extract and print details from the script. - scriptClass, addresses, reqSigs, err := btcscript.ExtractPkScriptAddrs( + scriptClass, addresses, reqSigs, err := txscript.ExtractPkScriptAddrs( script, &btcnet.MainNetParams) if err != nil { fmt.Println(err) diff --git a/internal_test.go b/txscript/internal_test.go similarity index 99% rename from internal_test.go rename to txscript/internal_test.go index fa2bf539..1bd9cd47 100644 --- a/internal_test.go +++ b/txscript/internal_test.go @@ -1,8 +1,8 @@ -// Copyright (c) 2013-2014 Conformal Systems LLC. +// Copyright (c) 2013-2015 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. -package btcscript +package txscript import ( "encoding/hex" diff --git a/log.go b/txscript/log.go similarity index 96% rename from log.go rename to txscript/log.go index 8f7cc5cf..60d86926 100644 --- a/log.go +++ b/txscript/log.go @@ -1,8 +1,8 @@ -// Copyright (c) 2013-2014 Conformal Systems LLC. +// Copyright (c) 2013-2015 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. -package btcscript +package txscript import ( "errors" diff --git a/log_test.go b/txscript/log_test.go similarity index 88% rename from log_test.go rename to txscript/log_test.go index 3b740de1..15f369c1 100644 --- a/log_test.go +++ b/txscript/log_test.go @@ -1,8 +1,8 @@ -// Copyright (c) 2013-2014 Conformal Systems LLC. +// Copyright (c) 2013-2015 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. -package btcscript_test +package txscript_test import ( "errors" @@ -10,7 +10,7 @@ import ( "os" "testing" - "github.com/btcsuite/btcscript" + "github.com/btcsuite/btcd/txscript" ) func TestSetLogWriter(t *testing.T) { @@ -48,7 +48,7 @@ func TestSetLogWriter(t *testing.T) { t.Logf("Running %d tests", len(tests)) for i, test := range tests { - err := btcscript.SetLogWriter(test.w, test.level) + err := txscript.SetLogWriter(test.w, test.level) if err != nil { if err.Error() != test.expected.Error() { t.Errorf("SetLogWriter #%d (%s) wrong result\n"+ diff --git a/opcode.go b/txscript/opcode.go similarity index 99% rename from opcode.go rename to txscript/opcode.go index 07d6b30f..6ae2f58c 100644 --- a/opcode.go +++ b/txscript/opcode.go @@ -1,8 +1,8 @@ -// Copyright (c) 2013-2014 Conformal Systems LLC. +// Copyright (c) 2013-2015 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. -package btcscript +package txscript import ( "bytes" @@ -20,7 +20,7 @@ import ( "github.com/btcsuite/fastsha256" ) -// An opcode defines the information related to a btcscript opcode. +// An opcode defines the information related to a txscript opcode. // opfunc if present is the function to call to perform the opcode on // the script. The current script is passed in as a slice with the firs // member being the opcode itself. diff --git a/opcode_test.go b/txscript/opcode_test.go similarity index 64% rename from opcode_test.go rename to txscript/opcode_test.go index 9b4ac4d8..b237df11 100644 --- a/opcode_test.go +++ b/txscript/opcode_test.go @@ -1,14 +1,14 @@ -// Copyright (c) 2013-2014 Conformal Systems LLC. +// Copyright (c) 2013-2015 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. -package btcscript_test +package txscript_test import ( "bytes" "testing" - "github.com/btcsuite/btcscript" + "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcwire" ) @@ -24,357 +24,357 @@ func TestScripts(t *testing.T) { shouldFail error }{ // does nothing, but doesn't put a true on the stack, should fail - {script: []byte{btcscript.OP_NOP}, shouldPass: false}, + {script: []byte{txscript.OP_NOP}, shouldPass: false}, // should just put true on the stack, thus passes. - {script: []byte{btcscript.OP_TRUE}, shouldPass: true}, + {script: []byte{txscript.OP_TRUE}, shouldPass: true}, // should just put false on the stack, thus fails. - {script: []byte{btcscript.OP_FALSE}, shouldPass: false}, + {script: []byte{txscript.OP_FALSE}, shouldPass: false}, // tests OP_VERIFY (true). true is needed since else stack is empty. - {script: []byte{btcscript.OP_TRUE, btcscript.OP_VERIFY, - btcscript.OP_TRUE}, shouldPass: true}, + {script: []byte{txscript.OP_TRUE, txscript.OP_VERIFY, + txscript.OP_TRUE}, shouldPass: true}, // tests OP_VERIFY (false), will error out. - {script: []byte{btcscript.OP_FALSE, btcscript.OP_VERIFY, - btcscript.OP_TRUE}, shouldPass: false}, + {script: []byte{txscript.OP_FALSE, txscript.OP_VERIFY, + txscript.OP_TRUE}, shouldPass: false}, // tests OP_VERIFY with empty stack (errors) - {script: []byte{btcscript.OP_VERIFY}, shouldPass: false}, + {script: []byte{txscript.OP_VERIFY}, shouldPass: false}, // test OP_RETURN immediately fails the script (empty stack) - {script: []byte{btcscript.OP_RETURN}, shouldPass: false}, + {script: []byte{txscript.OP_RETURN}, shouldPass: false}, // test OP_RETURN immediately fails the script (full stack) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_RETURN}, + {script: []byte{txscript.OP_TRUE, txscript.OP_RETURN}, shouldPass: false}, // tests numequal with a trivial example (passing) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_NUMEQUAL}, shouldPass: true}, + {script: []byte{txscript.OP_TRUE, txscript.OP_TRUE, + txscript.OP_NUMEQUAL}, shouldPass: true}, // tests numequal with a trivial example (failing) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_NUMEQUAL}, shouldPass: false}, + {script: []byte{txscript.OP_TRUE, txscript.OP_FALSE, + txscript.OP_NUMEQUAL}, shouldPass: false}, // tests numequal with insufficient arguments (1/2) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_NUMEQUAL}, + {script: []byte{txscript.OP_TRUE, txscript.OP_NUMEQUAL}, shouldPass: false}, // tests numequal with insufficient arguments (0/2) - {script: []byte{btcscript.OP_NUMEQUAL}, shouldPass: false}, + {script: []byte{txscript.OP_NUMEQUAL}, shouldPass: false}, // tests numnotequal with a trivial example (passing) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_NUMNOTEQUAL}, shouldPass: true}, + {script: []byte{txscript.OP_TRUE, txscript.OP_FALSE, + txscript.OP_NUMNOTEQUAL}, shouldPass: true}, // tests numnotequal with a trivial example (failing) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_NUMNOTEQUAL}, shouldPass: false}, + {script: []byte{txscript.OP_TRUE, txscript.OP_TRUE, + txscript.OP_NUMNOTEQUAL}, shouldPass: false}, // tests numnotequal with insufficient arguments (1/2) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_NUMNOTEQUAL}, + {script: []byte{txscript.OP_TRUE, txscript.OP_NUMNOTEQUAL}, shouldPass: false}, // tests numnotequal with insufficient arguments (0/2) - {script: []byte{btcscript.OP_NUMNOTEQUAL}, shouldPass: false}, + {script: []byte{txscript.OP_NUMNOTEQUAL}, shouldPass: false}, // test numequal_verify with a trivial example (passing) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_NUMEQUALVERIFY, btcscript.OP_TRUE}, + {script: []byte{txscript.OP_TRUE, txscript.OP_TRUE, + txscript.OP_NUMEQUALVERIFY, txscript.OP_TRUE}, shouldPass: true}, // test numequal_verify with a trivial example (failing) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_NUMEQUALVERIFY, btcscript.OP_TRUE}, + {script: []byte{txscript.OP_TRUE, txscript.OP_FALSE, + txscript.OP_NUMEQUALVERIFY, txscript.OP_TRUE}, shouldPass: false}, // test OP_1ADD by adding 1 to 0 - {script: []byte{btcscript.OP_FALSE, btcscript.OP_1ADD}, + {script: []byte{txscript.OP_FALSE, txscript.OP_1ADD}, shouldPass: true}, // test OP_1ADD without args (should error) - {script: []byte{btcscript.OP_1ADD}, shouldPass: false}, + {script: []byte{txscript.OP_1ADD}, shouldPass: false}, // test OP_1NEGATE by adding 1 to -1 - {script: []byte{btcscript.OP_1NEGATE, btcscript.OP_1ADD}, + {script: []byte{txscript.OP_1NEGATE, txscript.OP_1ADD}, shouldPass: false}, // test OP_1NEGATE by adding negating -1 - {script: []byte{btcscript.OP_1NEGATE, btcscript.OP_NEGATE}, + {script: []byte{txscript.OP_1NEGATE, txscript.OP_NEGATE}, shouldPass: true}, // test OP_NEGATE by adding 1 to -1 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_NEGATE, - btcscript.OP_1ADD}, shouldPass: false}, + {script: []byte{txscript.OP_TRUE, txscript.OP_NEGATE, + txscript.OP_1ADD}, shouldPass: false}, // test OP_NEGATE with no args - {script: []byte{btcscript.OP_NEGATE}, shouldPass: false}, + {script: []byte{txscript.OP_NEGATE}, shouldPass: false}, // test OP_1SUB -> 1 - 1 = 0 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_1SUB}, + {script: []byte{txscript.OP_TRUE, txscript.OP_1SUB}, shouldPass: false}, // test OP_1SUB -> negate(0 -1) = 1 - {script: []byte{btcscript.OP_FALSE, btcscript.OP_1SUB, - btcscript.OP_NEGATE}, shouldPass: true}, + {script: []byte{txscript.OP_FALSE, txscript.OP_1SUB, + txscript.OP_NEGATE}, shouldPass: true}, // test OP_1SUB with empty stack - {script: []byte{btcscript.OP_1SUB}, shouldPass: false}, + {script: []byte{txscript.OP_1SUB}, shouldPass: false}, // OP_DEPTH with empty stack, means 0 on stack at end - {script: []byte{btcscript.OP_DEPTH}, shouldPass: false}, + {script: []byte{txscript.OP_DEPTH}, shouldPass: false}, // 1 +1 -1 = 1. tests depth + add - {script: []byte{btcscript.OP_TRUE, btcscript.OP_DEPTH, btcscript.OP_ADD, - btcscript.OP_1SUB}, shouldPass: true}, + {script: []byte{txscript.OP_TRUE, txscript.OP_DEPTH, txscript.OP_ADD, + txscript.OP_1SUB}, shouldPass: true}, // 1 +1 -1 = 0 . tests dept + add - {script: []byte{btcscript.OP_TRUE, btcscript.OP_DEPTH, - btcscript.OP_ADD, btcscript.OP_1SUB, btcscript.OP_1SUB}, + {script: []byte{txscript.OP_TRUE, txscript.OP_DEPTH, + txscript.OP_ADD, txscript.OP_1SUB, txscript.OP_1SUB}, shouldPass: false}, // OP_ADD with only one thing on stack should error - {script: []byte{btcscript.OP_TRUE, btcscript.OP_ADD}, + {script: []byte{txscript.OP_TRUE, txscript.OP_ADD}, shouldPass: false}, // OP_ADD with nothing on stack should error - {script: []byte{btcscript.OP_ADD}, shouldPass: false}, + {script: []byte{txscript.OP_ADD}, shouldPass: false}, // OP_SUB: 1-1=0 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_SUB}, shouldPass: false}, + {script: []byte{txscript.OP_TRUE, txscript.OP_TRUE, + txscript.OP_SUB}, shouldPass: false}, // OP_SUB: 1+1-1=1 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_ADD, btcscript.OP_SUB}, shouldPass: true}, + {script: []byte{txscript.OP_TRUE, txscript.OP_TRUE, txscript.OP_TRUE, + txscript.OP_ADD, txscript.OP_SUB}, shouldPass: true}, // OP_SUB with only one thing on stack should error - {script: []byte{btcscript.OP_TRUE, btcscript.OP_SUB}, + {script: []byte{txscript.OP_TRUE, txscript.OP_SUB}, shouldPass: false}, // OP_SUB with nothing on stack should error - {script: []byte{btcscript.OP_SUB}, shouldPass: false}, + {script: []byte{txscript.OP_SUB}, shouldPass: false}, // OP_LESSTHAN 1 < 1 == false - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_LESSTHAN}, shouldPass: false}, + {script: []byte{txscript.OP_TRUE, txscript.OP_TRUE, + txscript.OP_LESSTHAN}, shouldPass: false}, // OP_LESSTHAN 1 < 0 == false - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_LESSTHAN}, shouldPass: false}, + {script: []byte{txscript.OP_TRUE, txscript.OP_FALSE, + txscript.OP_LESSTHAN}, shouldPass: false}, // OP_LESSTHAN 0 < 1 == true - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, - btcscript.OP_LESSTHAN}, shouldPass: true}, + {script: []byte{txscript.OP_FALSE, txscript.OP_TRUE, + txscript.OP_LESSTHAN}, shouldPass: true}, // OP_LESSTHAN only one arg - {script: []byte{btcscript.OP_TRUE, btcscript.OP_LESSTHAN}, + {script: []byte{txscript.OP_TRUE, txscript.OP_LESSTHAN}, shouldPass: false}, // OP_LESSTHAN no args - {script: []byte{btcscript.OP_LESSTHAN}, shouldPass: false}, + {script: []byte{txscript.OP_LESSTHAN}, shouldPass: false}, // OP_LESSTHANOREQUAL 1 <= 1 == true - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_LESSTHANOREQUAL}, shouldPass: true}, + {script: []byte{txscript.OP_TRUE, txscript.OP_TRUE, + txscript.OP_LESSTHANOREQUAL}, shouldPass: true}, // OP_LESSTHANOREQUAL 1 <= 0 == false - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_LESSTHANOREQUAL}, shouldPass: false}, + {script: []byte{txscript.OP_TRUE, txscript.OP_FALSE, + txscript.OP_LESSTHANOREQUAL}, shouldPass: false}, // OP_LESSTHANOREQUAL 0 <= 1 == true - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, - btcscript.OP_LESSTHANOREQUAL}, shouldPass: true}, + {script: []byte{txscript.OP_FALSE, txscript.OP_TRUE, + txscript.OP_LESSTHANOREQUAL}, shouldPass: true}, // OP_LESSTHANOREQUAL only one arg - {script: []byte{btcscript.OP_TRUE, btcscript.OP_LESSTHANOREQUAL}, + {script: []byte{txscript.OP_TRUE, txscript.OP_LESSTHANOREQUAL}, shouldPass: false}, // OP_LESSTHANOREQUAL no args - {script: []byte{btcscript.OP_LESSTHANOREQUAL}, shouldPass: false}, + {script: []byte{txscript.OP_LESSTHANOREQUAL}, shouldPass: false}, // OP_GREATERTHAN 1 > 1 == false - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_GREATERTHAN}, shouldPass: false}, + {script: []byte{txscript.OP_TRUE, txscript.OP_TRUE, + txscript.OP_GREATERTHAN}, shouldPass: false}, // OP_GREATERTHAN 1 > 0 == true - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_GREATERTHAN}, shouldPass: true}, + {script: []byte{txscript.OP_TRUE, txscript.OP_FALSE, + txscript.OP_GREATERTHAN}, shouldPass: true}, // OP_GREATERTHAN 0 > 1 == false - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, - btcscript.OP_GREATERTHAN}, shouldPass: false}, + {script: []byte{txscript.OP_FALSE, txscript.OP_TRUE, + txscript.OP_GREATERTHAN}, shouldPass: false}, // OP_GREATERTHAN only one arg - {script: []byte{btcscript.OP_TRUE, btcscript.OP_GREATERTHAN}, + {script: []byte{txscript.OP_TRUE, txscript.OP_GREATERTHAN}, shouldPass: false}, // OP_GREATERTHAN no args - {script: []byte{btcscript.OP_GREATERTHAN}, shouldPass: false}, + {script: []byte{txscript.OP_GREATERTHAN}, shouldPass: false}, // OP_GREATERTHANOREQUAL 1 >= 1 == true - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_GREATERTHANOREQUAL}, shouldPass: true}, + {script: []byte{txscript.OP_TRUE, txscript.OP_TRUE, + txscript.OP_GREATERTHANOREQUAL}, shouldPass: true}, // OP_GREATERTHANOREQUAL 1 >= 0 == false - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_GREATERTHANOREQUAL}, shouldPass: true}, + {script: []byte{txscript.OP_TRUE, txscript.OP_FALSE, + txscript.OP_GREATERTHANOREQUAL}, shouldPass: true}, // OP_GREATERTHANOREQUAL 0 >= 1 == true - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, - btcscript.OP_GREATERTHANOREQUAL}, shouldPass: false}, + {script: []byte{txscript.OP_FALSE, txscript.OP_TRUE, + txscript.OP_GREATERTHANOREQUAL}, shouldPass: false}, // OP_GREATERTHANOREQUAL only one arg - {script: []byte{btcscript.OP_TRUE, btcscript.OP_GREATERTHANOREQUAL}, + {script: []byte{txscript.OP_TRUE, txscript.OP_GREATERTHANOREQUAL}, shouldPass: false}, // OP_GREATERTHANOREQUAL no args - {script: []byte{btcscript.OP_GREATERTHANOREQUAL}, shouldPass: false}, + {script: []byte{txscript.OP_GREATERTHANOREQUAL}, shouldPass: false}, // OP_MIN basic functionality -> min(0,1) = 0 = min(1,0) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_MIN}, shouldPass: false}, - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, - btcscript.OP_MIN}, shouldPass: false}, + {script: []byte{txscript.OP_TRUE, txscript.OP_FALSE, + txscript.OP_MIN}, shouldPass: false}, + {script: []byte{txscript.OP_FALSE, txscript.OP_TRUE, + txscript.OP_MIN}, shouldPass: false}, // OP_MIN -> 1 arg errors - {script: []byte{btcscript.OP_TRUE, btcscript.OP_MIN}, + {script: []byte{txscript.OP_TRUE, txscript.OP_MIN}, shouldPass: false}, // OP_MIN -> 0 arg errors - {script: []byte{btcscript.OP_MIN}, shouldPass: false}, + {script: []byte{txscript.OP_MIN}, shouldPass: false}, // OP_MAX basic functionality -> max(0,1) = 1 = max(1,0) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_MAX}, shouldPass: true}, - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, - btcscript.OP_MAX}, shouldPass: true}, + {script: []byte{txscript.OP_TRUE, txscript.OP_FALSE, + txscript.OP_MAX}, shouldPass: true}, + {script: []byte{txscript.OP_FALSE, txscript.OP_TRUE, + txscript.OP_MAX}, shouldPass: true}, // OP_MAX -> 1 arg errors - {script: []byte{btcscript.OP_TRUE, btcscript.OP_MAX}, + {script: []byte{txscript.OP_TRUE, txscript.OP_MAX}, shouldPass: false}, // OP_MAX -> 0 arg errors - {script: []byte{btcscript.OP_MAX}, shouldPass: false}, + {script: []byte{txscript.OP_MAX}, shouldPass: false}, // By this point we know a number of operations appear to be working // correctly. we can use them to test the other number pushing // operations - {script: []byte{btcscript.OP_TRUE, btcscript.OP_1ADD, btcscript.OP_2, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_2, btcscript.OP_1ADD, btcscript.OP_3, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_3, btcscript.OP_1ADD, btcscript.OP_4, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_4, btcscript.OP_1ADD, btcscript.OP_5, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_5, btcscript.OP_1ADD, btcscript.OP_6, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_6, btcscript.OP_1ADD, btcscript.OP_7, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_7, btcscript.OP_1ADD, btcscript.OP_8, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_8, btcscript.OP_1ADD, btcscript.OP_9, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_9, btcscript.OP_1ADD, btcscript.OP_10, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_10, btcscript.OP_1ADD, btcscript.OP_11, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_11, btcscript.OP_1ADD, btcscript.OP_12, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_12, btcscript.OP_1ADD, btcscript.OP_13, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_13, btcscript.OP_1ADD, btcscript.OP_14, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_14, btcscript.OP_1ADD, btcscript.OP_15, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_15, btcscript.OP_1ADD, btcscript.OP_16, - btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{txscript.OP_TRUE, txscript.OP_1ADD, txscript.OP_2, + txscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{txscript.OP_2, txscript.OP_1ADD, txscript.OP_3, + txscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{txscript.OP_3, txscript.OP_1ADD, txscript.OP_4, + txscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{txscript.OP_4, txscript.OP_1ADD, txscript.OP_5, + txscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{txscript.OP_5, txscript.OP_1ADD, txscript.OP_6, + txscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{txscript.OP_6, txscript.OP_1ADD, txscript.OP_7, + txscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{txscript.OP_7, txscript.OP_1ADD, txscript.OP_8, + txscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{txscript.OP_8, txscript.OP_1ADD, txscript.OP_9, + txscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{txscript.OP_9, txscript.OP_1ADD, txscript.OP_10, + txscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{txscript.OP_10, txscript.OP_1ADD, txscript.OP_11, + txscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{txscript.OP_11, txscript.OP_1ADD, txscript.OP_12, + txscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{txscript.OP_12, txscript.OP_1ADD, txscript.OP_13, + txscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{txscript.OP_13, txscript.OP_1ADD, txscript.OP_14, + txscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{txscript.OP_14, txscript.OP_1ADD, txscript.OP_15, + txscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{txscript.OP_15, txscript.OP_1ADD, txscript.OP_16, + txscript.OP_EQUAL}, shouldPass: true}, // Test OP_WITHIN x, min, max // 0 <= 1 < 2 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, btcscript.OP_2, - btcscript.OP_WITHIN}, shouldPass: true}, + {script: []byte{txscript.OP_TRUE, txscript.OP_FALSE, txscript.OP_2, + txscript.OP_WITHIN}, shouldPass: true}, // 1 <= 0 < 2 FAIL - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, btcscript.OP_2, - btcscript.OP_WITHIN}, shouldPass: false}, + {script: []byte{txscript.OP_FALSE, txscript.OP_TRUE, txscript.OP_2, + txscript.OP_WITHIN}, shouldPass: false}, // 1 <= 1 < 2 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, btcscript.OP_2, - btcscript.OP_WITHIN}, shouldPass: true}, + {script: []byte{txscript.OP_TRUE, txscript.OP_TRUE, txscript.OP_2, + txscript.OP_WITHIN}, shouldPass: true}, // 1 <= 2 < 2 FAIL - {script: []byte{btcscript.OP_2, btcscript.OP_TRUE, btcscript.OP_2, - btcscript.OP_WITHIN}, shouldPass: false}, + {script: []byte{txscript.OP_2, txscript.OP_TRUE, txscript.OP_2, + txscript.OP_WITHIN}, shouldPass: false}, // only two arguments - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_WITHIN}, shouldPass: false}, + {script: []byte{txscript.OP_TRUE, txscript.OP_FALSE, + txscript.OP_WITHIN}, shouldPass: false}, // only one argument - {script: []byte{btcscript.OP_TRUE, btcscript.OP_WITHIN}, + {script: []byte{txscript.OP_TRUE, txscript.OP_WITHIN}, shouldPass: false}, // no arguments - {script: []byte{btcscript.OP_WITHIN}, shouldPass: false}, + {script: []byte{txscript.OP_WITHIN}, shouldPass: false}, // OP_BOOLAND // 1 && 1 == 1 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_BOOLAND}, shouldPass: true}, + {script: []byte{txscript.OP_TRUE, txscript.OP_TRUE, + txscript.OP_BOOLAND}, shouldPass: true}, // 1 && 0 == 0 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_BOOLAND}, shouldPass: false}, + {script: []byte{txscript.OP_TRUE, txscript.OP_FALSE, + txscript.OP_BOOLAND}, shouldPass: false}, // 0 && 1 == 0 - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, - btcscript.OP_BOOLAND}, shouldPass: false}, + {script: []byte{txscript.OP_FALSE, txscript.OP_TRUE, + txscript.OP_BOOLAND}, shouldPass: false}, // 0 && 0 == 0 - {script: []byte{btcscript.OP_FALSE, btcscript.OP_FALSE, - btcscript.OP_BOOLAND}, shouldPass: false}, + {script: []byte{txscript.OP_FALSE, txscript.OP_FALSE, + txscript.OP_BOOLAND}, shouldPass: false}, // 0 && - boom - {script: []byte{btcscript.OP_TRUE, btcscript.OP_BOOLAND}, + {script: []byte{txscript.OP_TRUE, txscript.OP_BOOLAND}, shouldPass: false}, // && - boom - {script: []byte{btcscript.OP_BOOLAND}, shouldPass: false}, + {script: []byte{txscript.OP_BOOLAND}, shouldPass: false}, // OP_BOOLOR // 1 || 1 == 1 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_BOOLOR}, shouldPass: true}, + {script: []byte{txscript.OP_TRUE, txscript.OP_TRUE, + txscript.OP_BOOLOR}, shouldPass: true}, // 1 || 0 == 1 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_BOOLOR}, shouldPass: true}, + {script: []byte{txscript.OP_TRUE, txscript.OP_FALSE, + txscript.OP_BOOLOR}, shouldPass: true}, // 0 || 1 == 1 - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, - btcscript.OP_BOOLOR}, shouldPass: true}, + {script: []byte{txscript.OP_FALSE, txscript.OP_TRUE, + txscript.OP_BOOLOR}, shouldPass: true}, // 0 || 0 == 0 - {script: []byte{btcscript.OP_FALSE, btcscript.OP_FALSE, - btcscript.OP_BOOLOR}, shouldPass: false}, + {script: []byte{txscript.OP_FALSE, txscript.OP_FALSE, + txscript.OP_BOOLOR}, shouldPass: false}, // 0 && - boom - {script: []byte{btcscript.OP_TRUE, btcscript.OP_BOOLOR}, + {script: []byte{txscript.OP_TRUE, txscript.OP_BOOLOR}, shouldPass: false}, // && - boom - {script: []byte{btcscript.OP_BOOLOR}, shouldPass: false}, + {script: []byte{txscript.OP_BOOLOR}, shouldPass: false}, // OP_0NOTEQUAL // 1 with input != 0 XXX check output is actually 1. - {script: []byte{btcscript.OP_TRUE, btcscript.OP_0NOTEQUAL}, + {script: []byte{txscript.OP_TRUE, txscript.OP_0NOTEQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_2, btcscript.OP_0NOTEQUAL}, + {script: []byte{txscript.OP_2, txscript.OP_0NOTEQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_3, btcscript.OP_0NOTEQUAL}, + {script: []byte{txscript.OP_3, txscript.OP_0NOTEQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_4, btcscript.OP_0NOTEQUAL}, + {script: []byte{txscript.OP_4, txscript.OP_0NOTEQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_5, btcscript.OP_0NOTEQUAL}, + {script: []byte{txscript.OP_5, txscript.OP_0NOTEQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_6, btcscript.OP_0NOTEQUAL}, + {script: []byte{txscript.OP_6, txscript.OP_0NOTEQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_7, btcscript.OP_0NOTEQUAL}, + {script: []byte{txscript.OP_7, txscript.OP_0NOTEQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_8, btcscript.OP_0NOTEQUAL}, + {script: []byte{txscript.OP_8, txscript.OP_0NOTEQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_9, btcscript.OP_0NOTEQUAL}, + {script: []byte{txscript.OP_9, txscript.OP_0NOTEQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_10, btcscript.OP_0NOTEQUAL}, + {script: []byte{txscript.OP_10, txscript.OP_0NOTEQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_11, btcscript.OP_0NOTEQUAL}, + {script: []byte{txscript.OP_11, txscript.OP_0NOTEQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_12, btcscript.OP_0NOTEQUAL}, + {script: []byte{txscript.OP_12, txscript.OP_0NOTEQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_13, btcscript.OP_0NOTEQUAL}, + {script: []byte{txscript.OP_13, txscript.OP_0NOTEQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_14, btcscript.OP_0NOTEQUAL}, + {script: []byte{txscript.OP_14, txscript.OP_0NOTEQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_15, btcscript.OP_0NOTEQUAL}, + {script: []byte{txscript.OP_15, txscript.OP_0NOTEQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_16, btcscript.OP_0NOTEQUAL}, + {script: []byte{txscript.OP_16, txscript.OP_0NOTEQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_FALSE, btcscript.OP_0NOTEQUAL}, shouldPass: false}, + {script: []byte{txscript.OP_FALSE, txscript.OP_0NOTEQUAL}, shouldPass: false}, // No arguments also blows up - {script: []byte{btcscript.OP_0NOTEQUAL}, shouldPass: false}, + {script: []byte{txscript.OP_0NOTEQUAL}, shouldPass: false}, // OP_NOT: 1 i input is 0, else 0 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_2, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_3, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_4, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_5, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_6, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_7, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_8, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_9, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_10, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_11, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_12, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_13, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_14, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_15, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_16, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{txscript.OP_TRUE, txscript.OP_NOT}, shouldPass: false}, + {script: []byte{txscript.OP_2, txscript.OP_NOT}, shouldPass: false}, + {script: []byte{txscript.OP_3, txscript.OP_NOT}, shouldPass: false}, + {script: []byte{txscript.OP_4, txscript.OP_NOT}, shouldPass: false}, + {script: []byte{txscript.OP_5, txscript.OP_NOT}, shouldPass: false}, + {script: []byte{txscript.OP_6, txscript.OP_NOT}, shouldPass: false}, + {script: []byte{txscript.OP_7, txscript.OP_NOT}, shouldPass: false}, + {script: []byte{txscript.OP_8, txscript.OP_NOT}, shouldPass: false}, + {script: []byte{txscript.OP_9, txscript.OP_NOT}, shouldPass: false}, + {script: []byte{txscript.OP_10, txscript.OP_NOT}, shouldPass: false}, + {script: []byte{txscript.OP_11, txscript.OP_NOT}, shouldPass: false}, + {script: []byte{txscript.OP_12, txscript.OP_NOT}, shouldPass: false}, + {script: []byte{txscript.OP_13, txscript.OP_NOT}, shouldPass: false}, + {script: []byte{txscript.OP_14, txscript.OP_NOT}, shouldPass: false}, + {script: []byte{txscript.OP_15, txscript.OP_NOT}, shouldPass: false}, + {script: []byte{txscript.OP_16, txscript.OP_NOT}, shouldPass: false}, // check negative numbers too - {script: []byte{btcscript.OP_TRUE, btcscript.OP_NEGATE, - btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_FALSE, btcscript.OP_NOT}, + {script: []byte{txscript.OP_TRUE, txscript.OP_NEGATE, + txscript.OP_NOT}, shouldPass: false}, + {script: []byte{txscript.OP_FALSE, txscript.OP_NOT}, shouldPass: true}, // No arguments also blows up - {script: []byte{btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{txscript.OP_NOT}, shouldPass: false}, // Conditional Execution - {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: true}, - {script: []byte{btcscript.OP_1, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: false}, - {script: []byte{btcscript.OP_1, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: true}, - {script: []byte{btcscript.OP_0, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: false}, - {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2}, shouldFail: btcscript.ErrStackMissingEndif}, - {script: []byte{btcscript.OP_1, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2}, shouldFail: btcscript.ErrStackMissingEndif}, - {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_IF, btcscript.OP_IF, btcscript.OP_1, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ENDIF}, shouldPass: true}, - {script: []byte{btcscript.OP_1, btcscript.OP_IF, btcscript.OP_IF, btcscript.OP_1, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ENDIF}, shouldFail: btcscript.ErrStackUnderflow}, - {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ELSE, btcscript.OP_1, btcscript.OP_ENDIF}, shouldPass: true}, - {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ELSE, btcscript.OP_1, btcscript.OP_ENDIF}, shouldPass: true}, - {script: []byte{btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ENDIF}, shouldFail: btcscript.ErrStackUnderflow}, - {script: []byte{btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF}, shouldFail: btcscript.ErrStackNoIf}, - {script: []byte{btcscript.OP_ENDIF}, shouldFail: btcscript.ErrStackNoIf}, + {script: []byte{txscript.OP_0, txscript.OP_IF, txscript.OP_0, txscript.OP_ELSE, txscript.OP_2, txscript.OP_ENDIF}, shouldPass: true}, + {script: []byte{txscript.OP_1, txscript.OP_IF, txscript.OP_0, txscript.OP_ELSE, txscript.OP_2, txscript.OP_ENDIF}, shouldPass: false}, + {script: []byte{txscript.OP_1, txscript.OP_NOTIF, txscript.OP_0, txscript.OP_ELSE, txscript.OP_2, txscript.OP_ENDIF}, shouldPass: true}, + {script: []byte{txscript.OP_0, txscript.OP_NOTIF, txscript.OP_0, txscript.OP_ELSE, txscript.OP_2, txscript.OP_ENDIF}, shouldPass: false}, + {script: []byte{txscript.OP_0, txscript.OP_IF, txscript.OP_0, txscript.OP_ELSE, txscript.OP_2}, shouldFail: txscript.ErrStackMissingEndif}, + {script: []byte{txscript.OP_1, txscript.OP_NOTIF, txscript.OP_0, txscript.OP_ELSE, txscript.OP_2}, shouldFail: txscript.ErrStackMissingEndif}, + {script: []byte{txscript.OP_1, txscript.OP_1, txscript.OP_IF, txscript.OP_IF, txscript.OP_1, txscript.OP_ELSE, txscript.OP_0, txscript.OP_ENDIF, txscript.OP_ENDIF}, shouldPass: true}, + {script: []byte{txscript.OP_1, txscript.OP_IF, txscript.OP_IF, txscript.OP_1, txscript.OP_ELSE, txscript.OP_0, txscript.OP_ENDIF, txscript.OP_ENDIF}, shouldFail: txscript.ErrStackUnderflow}, + {script: []byte{txscript.OP_0, txscript.OP_IF, txscript.OP_IF, txscript.OP_0, txscript.OP_ELSE, txscript.OP_0, txscript.OP_ENDIF, txscript.OP_ELSE, txscript.OP_1, txscript.OP_ENDIF}, shouldPass: true}, + {script: []byte{txscript.OP_0, txscript.OP_IF, txscript.OP_NOTIF, txscript.OP_0, txscript.OP_ELSE, txscript.OP_0, txscript.OP_ENDIF, txscript.OP_ELSE, txscript.OP_1, txscript.OP_ENDIF}, shouldPass: true}, + {script: []byte{txscript.OP_NOTIF, txscript.OP_0, txscript.OP_ENDIF}, shouldFail: txscript.ErrStackUnderflow}, + {script: []byte{txscript.OP_ELSE, txscript.OP_0, txscript.OP_ENDIF}, shouldFail: txscript.ErrStackNoIf}, + {script: []byte{txscript.OP_ENDIF}, shouldFail: txscript.ErrStackNoIf}, /* up here because error from sig parsing is undefined. */ - {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_DATA_65, + {script: []byte{txscript.OP_1, txscript.OP_1, txscript.OP_DATA_65, 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, 0x71, 0x30, 0x2f, @@ -382,10 +382,10 @@ func TestScripts(t *testing.T) { 0xa7, 0xdf, 0x5f, 0x14, 0x2c, 0x21, 0xc1, 0xb7, 0x30, 0x3b, 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, - btcscript.OP_1, btcscript.OP_CHECKMULTISIG}, + txscript.OP_1, txscript.OP_CHECKMULTISIG}, canonical: false, shouldPass: false}, - {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_DATA_65, + {script: []byte{txscript.OP_1, txscript.OP_1, txscript.OP_DATA_65, 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, 0x71, 0x30, 0x2f, @@ -393,11 +393,11 @@ func TestScripts(t *testing.T) { 0xa7, 0xdf, 0x5f, 0x14, 0x2c, 0x21, 0xc1, 0xb7, 0x30, 0x3b, 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, - btcscript.OP_1, btcscript.OP_CHECKMULTISIG}, + txscript.OP_1, txscript.OP_CHECKMULTISIG}, canonical: true, shouldPass: false}, /* up here because no defined error case. */ - {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_DATA_65, + {script: []byte{txscript.OP_1, txscript.OP_1, txscript.OP_DATA_65, 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, 0x71, 0x30, 0x2f, @@ -405,7 +405,7 @@ func TestScripts(t *testing.T) { 0xa7, 0xdf, 0x5f, 0x14, 0x2c, 0x21, 0xc1, 0xb7, 0x30, 0x3b, 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, - btcscript.OP_1, btcscript.OP_CHECKMULTISIGVERIFY}, + txscript.OP_1, txscript.OP_CHECKMULTISIGVERIFY}, shouldPass: false}, // Invalid Opcodes @@ -488,7 +488,7 @@ func TestScripts(t *testing.T) { Hash: btcwire.ShaHash{}, Index: 0xffffffff, }, - SignatureScript: []byte{btcscript.OP_NOP}, + SignatureScript: []byte{txscript.OP_NOP}, Sequence: 0xffffffff, }, }, @@ -503,13 +503,13 @@ func TestScripts(t *testing.T) { for i, test := range tests { // Parse and execute the test script. - var flags btcscript.ScriptFlags + var flags txscript.ScriptFlags if test.canonical { - flags = btcscript.ScriptCanonicalSignatures + flags = txscript.ScriptCanonicalSignatures } mockTx.TxOut[0].PkScript = test.script sigScript := mockTx.TxIn[0].SignatureScript - engine, err := btcscript.NewScript(sigScript, test.script, 0, + engine, err := txscript.NewScript(sigScript, test.script, 0, mockTx, flags) if err == nil { err = engine.Execute() @@ -557,317 +557,317 @@ var detailedTests = []detailedTest{ { name: "noop", before: [][]byte{{1}, {2}, {3}, {4}, {5}}, - script: []byte{btcscript.OP_NOP}, + script: []byte{txscript.OP_NOP}, after: [][]byte{{1}, {2}, {3}, {4}, {5}}, disassembly: "OP_NOP", }, { name: "dup", before: [][]byte{{1}}, - script: []byte{btcscript.OP_DUP}, + script: []byte{txscript.OP_DUP}, after: [][]byte{{1}, {1}}, disassembly: "OP_DUP", }, { name: "dup2", before: [][]byte{{1}, {2}}, - script: []byte{btcscript.OP_2DUP}, + script: []byte{txscript.OP_2DUP}, after: [][]byte{{1}, {2}, {1}, {2}}, disassembly: "OP_2DUP", }, { name: "dup3", before: [][]byte{{1}, {2}, {3}}, - script: []byte{btcscript.OP_3DUP}, + script: []byte{txscript.OP_3DUP}, after: [][]byte{{1}, {2}, {3}, {1}, {2}, {3}}, disassembly: "OP_3DUP", }, { name: "dup too much", before: [][]byte{}, - script: []byte{btcscript.OP_DUP}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_DUP}, + expectedReturn: txscript.ErrStackUnderflow, after: [][]byte{}, disassembly: "OP_DUP", }, { name: "2dup too much", before: [][]byte{{1}}, - script: []byte{btcscript.OP_2DUP}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_2DUP}, + expectedReturn: txscript.ErrStackUnderflow, after: [][]byte{}, disassembly: "OP_2DUP", }, { name: "2dup way too much", before: [][]byte{}, - script: []byte{btcscript.OP_2DUP}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_2DUP}, + expectedReturn: txscript.ErrStackUnderflow, after: [][]byte{}, disassembly: "OP_2DUP", }, { name: "3dup too much", before: [][]byte{{1}, {2}}, - script: []byte{btcscript.OP_3DUP}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_3DUP}, + expectedReturn: txscript.ErrStackUnderflow, after: [][]byte{}, disassembly: "OP_3DUP", }, { name: "3dup kinda too much", before: [][]byte{{1}}, - script: []byte{btcscript.OP_3DUP}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_3DUP}, + expectedReturn: txscript.ErrStackUnderflow, after: [][]byte{}, disassembly: "OP_3DUP", }, { name: "3dup way too much", before: [][]byte{}, - script: []byte{btcscript.OP_3DUP}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_3DUP}, + expectedReturn: txscript.ErrStackUnderflow, after: [][]byte{}, disassembly: "OP_3DUP", }, { name: "Nip", before: [][]byte{{1}, {2}, {3}}, - script: []byte{btcscript.OP_NIP}, + script: []byte{txscript.OP_NIP}, after: [][]byte{{1}, {3}}, disassembly: "OP_NIP", }, { name: "Nip too much", before: [][]byte{{1}}, - script: []byte{btcscript.OP_NIP}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_NIP}, + expectedReturn: txscript.ErrStackUnderflow, after: [][]byte{{2}, {3}}, disassembly: "OP_NIP", }, { name: "keep on tucking", before: [][]byte{{1}, {2}, {3}}, - script: []byte{btcscript.OP_TUCK}, + script: []byte{txscript.OP_TUCK}, after: [][]byte{{1}, {3}, {2}, {3}}, disassembly: "OP_TUCK", }, { name: "a little tucked up", before: [][]byte{{1}}, // too few arguments for tuck - script: []byte{btcscript.OP_TUCK}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_TUCK}, + expectedReturn: txscript.ErrStackUnderflow, after: [][]byte{}, disassembly: "OP_TUCK", }, { name: "all tucked up", before: [][]byte{}, // too few arguments for tuck - script: []byte{btcscript.OP_TUCK}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_TUCK}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_TUCK", }, { name: "drop 1", before: [][]byte{{1}, {2}, {3}, {4}}, - script: []byte{btcscript.OP_DROP}, + script: []byte{txscript.OP_DROP}, after: [][]byte{{1}, {2}, {3}}, disassembly: "OP_DROP", }, { name: "drop 2", before: [][]byte{{1}, {2}, {3}, {4}}, - script: []byte{btcscript.OP_2DROP}, + script: []byte{txscript.OP_2DROP}, after: [][]byte{{1}, {2}}, disassembly: "OP_2DROP", }, { name: "drop too much", before: [][]byte{}, - script: []byte{btcscript.OP_DROP}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_DROP}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_DROP", }, { name: "2drop too much", before: [][]byte{{1}}, - script: []byte{btcscript.OP_2DROP}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_2DROP}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_2DROP", }, { name: "2drop far too much", before: [][]byte{}, - script: []byte{btcscript.OP_2DROP}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_2DROP}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_2DROP", }, { name: "Rot1", before: [][]byte{{1}, {2}, {3}, {4}}, - script: []byte{btcscript.OP_ROT}, + script: []byte{txscript.OP_ROT}, after: [][]byte{{1}, {3}, {4}, {2}}, disassembly: "OP_ROT", }, { name: "Rot2", before: [][]byte{{1}, {2}, {3}, {4}, {5}, {6}}, - script: []byte{btcscript.OP_2ROT}, + script: []byte{txscript.OP_2ROT}, after: [][]byte{{3}, {4}, {5}, {6}, {1}, {2}}, disassembly: "OP_2ROT", }, { name: "Rot too little", before: [][]byte{{1}, {2}}, - script: []byte{btcscript.OP_ROT}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_ROT}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_ROT", }, { name: "Swap1", before: [][]byte{{1}, {2}, {3}, {4}}, - script: []byte{btcscript.OP_SWAP}, + script: []byte{txscript.OP_SWAP}, after: [][]byte{{1}, {2}, {4}, {3}}, disassembly: "OP_SWAP", }, { name: "Swap2", before: [][]byte{{1}, {2}, {3}, {4}}, - script: []byte{btcscript.OP_2SWAP}, + script: []byte{txscript.OP_2SWAP}, after: [][]byte{{3}, {4}, {1}, {2}}, disassembly: "OP_2SWAP", }, { name: "Swap too little", before: [][]byte{{1}}, - script: []byte{btcscript.OP_SWAP}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_SWAP}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_SWAP", }, { name: "Over1", before: [][]byte{{1}, {2}, {3}, {4}}, - script: []byte{btcscript.OP_OVER}, + script: []byte{txscript.OP_OVER}, after: [][]byte{{1}, {2}, {3}, {4}, {3}}, disassembly: "OP_OVER", }, { name: "Over2", before: [][]byte{{1}, {2}, {3}, {4}}, - script: []byte{btcscript.OP_2OVER}, + script: []byte{txscript.OP_2OVER}, after: [][]byte{{1}, {2}, {3}, {4}, {1}, {2}}, disassembly: "OP_2OVER", }, { name: "Over too little", before: [][]byte{{1}}, - script: []byte{btcscript.OP_OVER}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_OVER}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_OVER", }, { name: "Pick1", before: [][]byte{{1}, {2}, {3}, {4}, {1}}, - script: []byte{btcscript.OP_PICK}, + script: []byte{txscript.OP_PICK}, after: [][]byte{{1}, {2}, {3}, {4}, {3}}, disassembly: "OP_PICK", }, { name: "Pick2", before: [][]byte{{1}, {2}, {3}, {4}, {2}}, - script: []byte{btcscript.OP_PICK}, + script: []byte{txscript.OP_PICK}, after: [][]byte{{1}, {2}, {3}, {4}, {2}}, disassembly: "OP_PICK", }, { name: "Pick too little", before: [][]byte{{1}, {1}}, - script: []byte{btcscript.OP_PICK}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_PICK}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_PICK", }, { name: "Pick nothing", before: [][]byte{{}}, - script: []byte{btcscript.OP_PICK}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_PICK}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_PICK", }, { name: "Pick no args", before: [][]byte{}, - script: []byte{btcscript.OP_PICK}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_PICK}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_PICK", }, { name: "Pick stupid numbers", before: [][]byte{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, - script: []byte{btcscript.OP_PICK}, - expectedReturn: btcscript.ErrStackNumberTooBig, + script: []byte{txscript.OP_PICK}, + expectedReturn: txscript.ErrStackNumberTooBig, disassembly: "OP_PICK", }, { name: "Roll1", before: [][]byte{{1}, {2}, {3}, {4}, {1}}, - script: []byte{btcscript.OP_ROLL}, + script: []byte{txscript.OP_ROLL}, after: [][]byte{{1}, {2}, {4}, {3}}, disassembly: "OP_ROLL", }, { name: "Roll2", before: [][]byte{{1}, {2}, {3}, {4}, {2}}, - script: []byte{btcscript.OP_ROLL}, + script: []byte{txscript.OP_ROLL}, after: [][]byte{{1}, {3}, {4}, {2}}, disassembly: "OP_ROLL", }, { name: "Roll too little", before: [][]byte{{1}, {1}}, - script: []byte{btcscript.OP_ROLL}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_ROLL}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_ROLL", }, { name: "Roll nothing ", before: [][]byte{{1}}, - script: []byte{btcscript.OP_ROLL}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_ROLL}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_ROLL", }, { name: "Roll no args ", before: [][]byte{}, - script: []byte{btcscript.OP_ROLL}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_ROLL}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_ROLL", }, { name: "Roll stupid numbers", before: [][]byte{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, - script: []byte{btcscript.OP_ROLL}, - expectedReturn: btcscript.ErrStackNumberTooBig, + script: []byte{txscript.OP_ROLL}, + expectedReturn: txscript.ErrStackNumberTooBig, disassembly: "OP_ROLL", }, { name: "ifdup (positive)", before: [][]byte{{1}}, - script: []byte{btcscript.OP_IFDUP}, + script: []byte{txscript.OP_IFDUP}, after: [][]byte{{1}, {1}}, disassembly: "OP_IFDUP", }, { name: "ifdup (negative)", before: [][]byte{{0}}, - script: []byte{btcscript.OP_IFDUP}, + script: []byte{txscript.OP_IFDUP}, after: [][]byte{{0}}, disassembly: "OP_IFDUP", }, { name: "ifdup (empty)", before: [][]byte{}, - script: []byte{btcscript.OP_IFDUP}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_IFDUP}, + expectedReturn: txscript.ErrStackUnderflow, after: [][]byte{{0}}, disassembly: "OP_IFDUP", }, @@ -876,7 +876,7 @@ var detailedTests = []detailedTest{ name: "toaltstack", before: [][]byte{{1}}, altbefore: [][]byte{}, - script: []byte{btcscript.OP_TOALTSTACK}, + script: []byte{txscript.OP_TOALTSTACK}, after: [][]byte{}, altafter: [][]byte{}, disassembly: "OP_TOALTSTACK", @@ -885,15 +885,15 @@ var detailedTests = []detailedTest{ name: "toaltastack (empty)", before: [][]byte{}, altbefore: [][]byte{}, - script: []byte{btcscript.OP_TOALTSTACK}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_TOALTSTACK}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_TOALTSTACK", }, { name: "fromaltastack", before: [][]byte{}, altbefore: [][]byte{{1}}, - script: []byte{btcscript.OP_FROMALTSTACK}, + script: []byte{txscript.OP_FROMALTSTACK}, after: [][]byte{{1}}, altafter: [][]byte{}, disassembly: "OP_FROMALTSTACK", @@ -902,28 +902,28 @@ var detailedTests = []detailedTest{ name: "fromaltastack (empty)", before: [][]byte{}, altbefore: [][]byte{}, - script: []byte{btcscript.OP_FROMALTSTACK}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_FROMALTSTACK}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_FROMALTSTACK", }, { name: "op_size (1)", before: [][]byte{{1}}, - script: []byte{btcscript.OP_SIZE}, + script: []byte{txscript.OP_SIZE}, after: [][]byte{{1}, {1}}, disassembly: "OP_SIZE", }, { name: "op_size (5)", before: [][]byte{{1, 2, 3, 4, 5}}, - script: []byte{btcscript.OP_SIZE}, + script: []byte{txscript.OP_SIZE}, after: [][]byte{{1, 2, 3, 4, 5}, {5}}, disassembly: "OP_SIZE", }, { name: "op_size (0)", before: [][]byte{{}}, - script: []byte{btcscript.OP_SIZE}, + script: []byte{txscript.OP_SIZE}, // pushInt(0) actually gives an empty array, still counts as 0 after: [][]byte{{}, {}}, disassembly: "OP_SIZE", @@ -931,178 +931,178 @@ var detailedTests = []detailedTest{ { name: "op_size (invalid)", before: [][]byte{}, - script: []byte{btcscript.OP_SIZE}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_SIZE}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_SIZE", }, { name: "OP_EQUAL (valid)", before: [][]byte{{1, 2, 3, 4}, {1, 2, 3, 4}}, - script: []byte{btcscript.OP_EQUAL}, + script: []byte{txscript.OP_EQUAL}, after: [][]byte{{1}}, disassembly: "OP_EQUAL", }, { name: "OP_EQUAL (invalid)", before: [][]byte{{1, 2, 3, 4}, {1, 2, 3, 3}}, - script: []byte{btcscript.OP_EQUAL}, + script: []byte{txscript.OP_EQUAL}, after: [][]byte{{0}}, disassembly: "OP_EQUAL", }, { name: "OP_EQUAL (one arg)", before: [][]byte{{1, 2, 3, 4}}, - script: []byte{btcscript.OP_EQUAL}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_EQUAL}, + expectedReturn: txscript.ErrStackUnderflow, after: [][]byte{{0}}, disassembly: "OP_EQUAL", }, { name: "OP_EQUAL (no arg)", before: [][]byte{}, - script: []byte{btcscript.OP_EQUAL}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_EQUAL}, + expectedReturn: txscript.ErrStackUnderflow, after: [][]byte{{0}}, disassembly: "OP_EQUAL", }, { name: "OP_EQUALVERIFY (valid)", before: [][]byte{{1, 2, 3, 4}, {1, 2, 3, 4}}, - script: []byte{btcscript.OP_EQUALVERIFY}, + script: []byte{txscript.OP_EQUALVERIFY}, after: [][]byte{}, disassembly: "OP_EQUALVERIFY", }, { name: "OP_EQUALVERIFY (invalid)", before: [][]byte{{1, 2, 3, 4}, {1, 2, 3, 3}}, - script: []byte{btcscript.OP_EQUALVERIFY}, - expectedReturn: btcscript.ErrStackVerifyFailed, + script: []byte{txscript.OP_EQUALVERIFY}, + expectedReturn: txscript.ErrStackVerifyFailed, after: [][]byte{}, disassembly: "OP_EQUALVERIFY", }, { name: "OP_EQUALVERIFY (one arg)", before: [][]byte{{1, 2, 3, 4}}, - script: []byte{btcscript.OP_EQUALVERIFY}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_EQUALVERIFY}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_EQUALVERIFY", }, { name: "OP_EQUALVERIFY (no arg)", before: [][]byte{}, - script: []byte{btcscript.OP_EQUALVERIFY}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_EQUALVERIFY}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_EQUALVERIFY", }, { name: "OP_1NEGATE", before: [][]byte{}, - script: []byte{btcscript.OP_1NEGATE}, + script: []byte{txscript.OP_1NEGATE}, after: [][]byte{{0x81}}, disassembly: "-1", }, { name: "add one to minus one", before: [][]byte{}, - script: []byte{btcscript.OP_1NEGATE, btcscript.OP_1ADD}, + script: []byte{txscript.OP_1NEGATE, txscript.OP_1ADD}, after: [][]byte{{}}, // 0 disassembly: "-1 OP_1ADD", }, { name: "OP_ABS (positive)", before: [][]byte{{1}}, - script: []byte{btcscript.OP_ABS}, + script: []byte{txscript.OP_ABS}, after: [][]byte{{1}}, disassembly: "OP_ABS", }, { name: "OP_ABS (negative)", before: [][]byte{{0x81}}, - script: []byte{btcscript.OP_ABS}, + script: []byte{txscript.OP_ABS}, after: [][]byte{{1}}, disassembly: "OP_ABS", }, { name: "OP_ABS (empty)", before: [][]byte{}, - script: []byte{btcscript.OP_ABS}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_ABS}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_ABS", }, { name: "op_data_1", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_1, 1}, + script: []byte{txscript.OP_DATA_1, 1}, after: [][]byte{{1}}, disassembly: "01", }, { name: "op_data_2", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_2, 1, 2}, + script: []byte{txscript.OP_DATA_2, 1, 2}, after: [][]byte{{1, 2}}, disassembly: "0102", }, { name: "op_data_3", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_3, 1, 2, 3}, + script: []byte{txscript.OP_DATA_3, 1, 2, 3}, after: [][]byte{{1, 2, 3}}, disassembly: "010203", }, { name: "op_data_4", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_4, 1, 2, 3, 4}, + script: []byte{txscript.OP_DATA_4, 1, 2, 3, 4}, after: [][]byte{{1, 2, 3, 4}}, disassembly: "01020304", }, { name: "op_data_5", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_5, 1, 2, 3, 4, 5}, + script: []byte{txscript.OP_DATA_5, 1, 2, 3, 4, 5}, after: [][]byte{{1, 2, 3, 4, 5}}, disassembly: "0102030405", }, { name: "op_data_6", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_6, 1, 2, 3, 4, 5, 6}, + script: []byte{txscript.OP_DATA_6, 1, 2, 3, 4, 5, 6}, after: [][]byte{{1, 2, 3, 4, 5, 6}}, disassembly: "010203040506", }, { name: "op_data_7", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_7, 1, 2, 3, 4, 5, 6, 7}, + script: []byte{txscript.OP_DATA_7, 1, 2, 3, 4, 5, 6, 7}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7}}, disassembly: "01020304050607", }, { name: "op_data_8", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_8, 1, 2, 3, 4, 5, 6, 7, 8}, + script: []byte{txscript.OP_DATA_8, 1, 2, 3, 4, 5, 6, 7, 8}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8}}, disassembly: "0102030405060708", }, { name: "op_data_9", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_9, 1, 2, 3, 4, 5, 6, 7, 8, 9}, + script: []byte{txscript.OP_DATA_9, 1, 2, 3, 4, 5, 6, 7, 8, 9}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9}}, disassembly: "010203040506070809", }, { name: "op_data_10", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + script: []byte{txscript.OP_DATA_10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}, disassembly: "0102030405060708090a", }, { name: "op_data_11", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_11, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}, disassembly: "0102030405060708090a0b", @@ -1110,7 +1110,7 @@ var detailedTests = []detailedTest{ { name: "op_data_12", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_12, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}}, disassembly: "0102030405060708090a0b0c", @@ -1118,7 +1118,7 @@ var detailedTests = []detailedTest{ { name: "op_data_13", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_13, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}}, disassembly: "0102030405060708090a0b0c0d", @@ -1126,7 +1126,7 @@ var detailedTests = []detailedTest{ { name: "op_data_14", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_14, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}}, disassembly: "0102030405060708090a0b0c0d0e", @@ -1134,7 +1134,7 @@ var detailedTests = []detailedTest{ { name: "op_data_15", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_15, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}}, @@ -1143,7 +1143,7 @@ var detailedTests = []detailedTest{ { name: "op_data_16", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_16, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}}, @@ -1152,7 +1152,7 @@ var detailedTests = []detailedTest{ { name: "op_data_17", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_17, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_17, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}}, @@ -1161,7 +1161,7 @@ var detailedTests = []detailedTest{ { name: "op_data_18", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_18, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_18, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}}, @@ -1170,7 +1170,7 @@ var detailedTests = []detailedTest{ { name: "op_data_19", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_19, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_19, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}}, @@ -1179,7 +1179,7 @@ var detailedTests = []detailedTest{ { name: "op_data_20", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_20, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_20, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}}, @@ -1188,7 +1188,7 @@ var detailedTests = []detailedTest{ { name: "op_data_21", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_21, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_21, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21}}, @@ -1197,7 +1197,7 @@ var detailedTests = []detailedTest{ { name: "op_data_22", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_22, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_22, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, @@ -1207,7 +1207,7 @@ var detailedTests = []detailedTest{ { name: "op_data_23", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_23, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_23, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, @@ -1217,7 +1217,7 @@ var detailedTests = []detailedTest{ { name: "op_data_24", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_24, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_24, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, @@ -1227,7 +1227,7 @@ var detailedTests = []detailedTest{ { name: "op_data_25", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_25, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_25, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, @@ -1237,7 +1237,7 @@ var detailedTests = []detailedTest{ { name: "op_data_26", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_26, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_26, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, @@ -1247,7 +1247,7 @@ var detailedTests = []detailedTest{ { name: "op_data_27", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_27, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_27, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, @@ -1258,7 +1258,7 @@ var detailedTests = []detailedTest{ { name: "op_data_28", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_28, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_28, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, @@ -1269,7 +1269,7 @@ var detailedTests = []detailedTest{ { name: "op_data_29", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_29, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, @@ -1280,7 +1280,7 @@ var detailedTests = []detailedTest{ { name: "op_data_30", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_30, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_30, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, @@ -1291,7 +1291,7 @@ var detailedTests = []detailedTest{ { name: "op_data_31", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_31, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_31, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, @@ -1302,7 +1302,7 @@ var detailedTests = []detailedTest{ { name: "op_data_32", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_32, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, @@ -1313,7 +1313,7 @@ var detailedTests = []detailedTest{ { name: "op_data_33", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_33, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_33, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33}, after: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, @@ -1324,7 +1324,7 @@ var detailedTests = []detailedTest{ { name: "op_data_34", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_34, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_34, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34}, @@ -1336,7 +1336,7 @@ var detailedTests = []detailedTest{ { name: "op_data_35", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_35, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_35, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35}, @@ -1348,7 +1348,7 @@ var detailedTests = []detailedTest{ { name: "op_data_36", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_36, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_36, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36}, @@ -1360,7 +1360,7 @@ var detailedTests = []detailedTest{ { name: "op_data_37", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_37, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_37, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37}, @@ -1372,7 +1372,7 @@ var detailedTests = []detailedTest{ { name: "op_data_38", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_38, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_38, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38}, @@ -1384,7 +1384,7 @@ var detailedTests = []detailedTest{ { name: "op_data_39", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_39, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_39, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39}, @@ -1397,7 +1397,7 @@ var detailedTests = []detailedTest{ { name: "op_data_40", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_40, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_40, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40}, @@ -1410,7 +1410,7 @@ var detailedTests = []detailedTest{ { name: "op_data_41", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_41, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_41, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41}, @@ -1423,7 +1423,7 @@ var detailedTests = []detailedTest{ { name: "op_data_42", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_42, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_42, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42}, @@ -1436,7 +1436,7 @@ var detailedTests = []detailedTest{ { name: "op_data_43", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_43, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_43, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43}, @@ -1449,7 +1449,7 @@ var detailedTests = []detailedTest{ { name: "op_data_44", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_44, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_44, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44}, @@ -1462,7 +1462,7 @@ var detailedTests = []detailedTest{ { name: "op_data_45", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_45, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_45, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45}, @@ -1475,7 +1475,7 @@ var detailedTests = []detailedTest{ { name: "op_data_46", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_46, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_46, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1489,7 +1489,7 @@ var detailedTests = []detailedTest{ { name: "op_data_47", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_47, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_47, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1503,7 +1503,7 @@ var detailedTests = []detailedTest{ { name: "op_data_48", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_48, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_48, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1517,7 +1517,7 @@ var detailedTests = []detailedTest{ { name: "op_data_49", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_49, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_49, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1531,7 +1531,7 @@ var detailedTests = []detailedTest{ { name: "op_data_50", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_50, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_50, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1545,7 +1545,7 @@ var detailedTests = []detailedTest{ { name: "op_data_51", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_51, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_51, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1560,7 +1560,7 @@ var detailedTests = []detailedTest{ { name: "op_data_52", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_52, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_52, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1575,7 +1575,7 @@ var detailedTests = []detailedTest{ { name: "op_data_53", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_53, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_53, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1590,7 +1590,7 @@ var detailedTests = []detailedTest{ { name: "op_data_54", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_54, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_54, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1605,7 +1605,7 @@ var detailedTests = []detailedTest{ { name: "op_data_55", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_55, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_55, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1620,7 +1620,7 @@ var detailedTests = []detailedTest{ { name: "op_data_56", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_56, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_56, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1635,7 +1635,7 @@ var detailedTests = []detailedTest{ { name: "op_data_57", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_57, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_57, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1650,7 +1650,7 @@ var detailedTests = []detailedTest{ { name: "op_data_58", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_58, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_58, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1666,7 +1666,7 @@ var detailedTests = []detailedTest{ { name: "op_data_59", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_59, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_59, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1682,7 +1682,7 @@ var detailedTests = []detailedTest{ { name: "op_data_60", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_60, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_60, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1698,7 +1698,7 @@ var detailedTests = []detailedTest{ { name: "op_data_61", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_61, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_61, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1714,7 +1714,7 @@ var detailedTests = []detailedTest{ { name: "op_data_62", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_62, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_62, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1730,7 +1730,7 @@ var detailedTests = []detailedTest{ { name: "op_data_63", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_63, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_63, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1747,7 +1747,7 @@ var detailedTests = []detailedTest{ { name: "op_data_64", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_64, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1764,7 +1764,7 @@ var detailedTests = []detailedTest{ { name: "op_data_65", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_65, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_65, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1781,7 +1781,7 @@ var detailedTests = []detailedTest{ { name: "op_data_66", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_66, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_66, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1798,7 +1798,7 @@ var detailedTests = []detailedTest{ { name: "op_data_67", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_67, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_67, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1815,7 +1815,7 @@ var detailedTests = []detailedTest{ { name: "op_data_68", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_68, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_68, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1832,7 +1832,7 @@ var detailedTests = []detailedTest{ { name: "op_data_69", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_69, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_69, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1849,7 +1849,7 @@ var detailedTests = []detailedTest{ { name: "op_data_70", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_70, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_70, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1867,7 +1867,7 @@ var detailedTests = []detailedTest{ { name: "op_data_71", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_71, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_71, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1885,7 +1885,7 @@ var detailedTests = []detailedTest{ { name: "op_data_72", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_72, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_72, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1903,7 +1903,7 @@ var detailedTests = []detailedTest{ { name: "op_data_73", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_73, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_73, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1921,7 +1921,7 @@ var detailedTests = []detailedTest{ { name: "op_data_74", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_74, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_74, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1940,7 +1940,7 @@ var detailedTests = []detailedTest{ { name: "op_data_75", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_75, 1, 2, 3, 4, 5, 6, 7, 8, 9, + script: []byte{txscript.OP_DATA_75, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, @@ -1959,48 +1959,48 @@ var detailedTests = []detailedTest{ { name: "op_data too short", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_2, 1}, - expectedReturn: btcscript.ErrStackShortScript, - disassemblyerr: btcscript.ErrStackShortScript, + script: []byte{txscript.OP_DATA_2, 1}, + expectedReturn: txscript.ErrStackShortScript, + disassemblyerr: txscript.ErrStackShortScript, }, { name: "op_pushdata_1", before: [][]byte{}, - script: []byte{btcscript.OP_PUSHDATA1, 1, 2}, + script: []byte{txscript.OP_PUSHDATA1, 1, 2}, after: [][]byte{{2}}, disassembly: "02", }, { name: "op_pushdata_1 too short", - script: []byte{btcscript.OP_PUSHDATA1, 1}, - expectedReturn: btcscript.ErrStackShortScript, - disassemblyerr: btcscript.ErrStackShortScript, + script: []byte{txscript.OP_PUSHDATA1, 1}, + expectedReturn: txscript.ErrStackShortScript, + disassemblyerr: txscript.ErrStackShortScript, }, { name: "op_pushdata_2", before: [][]byte{}, - script: []byte{btcscript.OP_PUSHDATA2, 2, 0, 2, 4}, + script: []byte{txscript.OP_PUSHDATA2, 2, 0, 2, 4}, after: [][]byte{{2, 4}}, disassembly: "0204", }, { name: "op_pushdata_2 too short", - script: []byte{btcscript.OP_PUSHDATA2, 2, 0}, - expectedReturn: btcscript.ErrStackShortScript, - disassemblyerr: btcscript.ErrStackShortScript, + script: []byte{txscript.OP_PUSHDATA2, 2, 0}, + expectedReturn: txscript.ErrStackShortScript, + disassemblyerr: txscript.ErrStackShortScript, }, { name: "op_pushdata_4", before: [][]byte{}, - script: []byte{btcscript.OP_PUSHDATA4, 4, 0, 0, 0, 2, 4, 8, 16}, + script: []byte{txscript.OP_PUSHDATA4, 4, 0, 0, 0, 2, 4, 8, 16}, after: [][]byte{{2, 4, 8, 16}}, disassembly: "02040810", }, { name: "op_pushdata_4 too short", - script: []byte{btcscript.OP_PUSHDATA4, 4, 0, 0, 0}, - expectedReturn: btcscript.ErrStackShortScript, - disassemblyerr: btcscript.ErrStackShortScript, + script: []byte{txscript.OP_PUSHDATA4, 4, 0, 0, 0}, + expectedReturn: txscript.ErrStackShortScript, + disassemblyerr: txscript.ErrStackShortScript, }, // XXX also pushdata cases where the pushed data isn't long enough, // no real error type defined for that as of yet. @@ -2008,14 +2008,14 @@ var detailedTests = []detailedTest{ { name: "OP_SHA1 no args", before: [][]byte{}, - script: []byte{btcscript.OP_SHA1}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_SHA1}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_SHA1", }, { name: "OP_SHA1", before: [][]byte{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, - script: []byte{btcscript.OP_SHA1}, + script: []byte{txscript.OP_SHA1}, after: [][]byte{{0x5d, 0x21, 0x1b, 0xad, 0x8f, 0x4e, 0xe7, 0x0e, 0x16, 0xc7, 0xd3, 0x43, 0xa8, 0x38, 0xfc, 0x34, 0x4a, 0x1e, 0xd9, 0x61}}, @@ -2024,15 +2024,15 @@ var detailedTests = []detailedTest{ { name: "OP_SHA256 no args", before: [][]byte{}, - script: []byte{btcscript.OP_SHA256}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_SHA256}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_SHA256", }, { name: "OP_RIPEMD160 no args", before: [][]byte{}, - script: []byte{btcscript.OP_RIPEMD160}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_RIPEMD160}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_RIPEMD160", }, // data taken from transaction @@ -2050,7 +2050,7 @@ var detailedTests = []detailedTest{ 0xe9, 0x91, 0x94, 0xaa, 0x69, 0x27, 0xaf, 0xf2, 0x54, 0x16, 0xec, 0x48, 0x9d, 0x45, 0x3a, 0x80, 0x7e, 0x03, 0xc0, 0x83}}, - script: []byte{btcscript.OP_SHA256, btcscript.OP_RIPEMD160}, + script: []byte{txscript.OP_SHA256, txscript.OP_RIPEMD160}, after: [][]byte{{0x8b, 0xfa, 0x5c, 0x1f, 0x68, 0x5f, 0x13, 0x86, 0x3e, 0x74, 0x2e, 0x1b, 0xaf, 0x15, 0xf1, 0x71, 0xad, 0x49, 0x8b, 0x8f}}, @@ -2067,7 +2067,7 @@ var detailedTests = []detailedTest{ 0xe9, 0x91, 0x94, 0xaa, 0x69, 0x27, 0xaf, 0xf2, 0x54, 0x16, 0xec, 0x48, 0x9d, 0x45, 0x3a, 0x80, 0x7e, 0x03, 0xc0, 0x83}}, - script: []byte{btcscript.OP_HASH160}, + script: []byte{txscript.OP_HASH160}, after: [][]byte{{0x8b, 0xfa, 0x5c, 0x1f, 0x68, 0x5f, 0x13, 0x86, 0x3e, 0x74, 0x2e, 0x1b, 0xaf, 0x15, 0xf1, 0x71, 0xad, 0x49, 0x8b, 0x8f}}, @@ -2077,7 +2077,7 @@ var detailedTests = []detailedTest{ { name: "op_hash160 full script", before: [][]byte{}, - script: []byte{btcscript.OP_DATA_65, + script: []byte{txscript.OP_DATA_65, 0x04, 0x0f, 0xa4, 0x92, 0xe3, 0x59, 0xde, 0xe8, 0x4b, 0x53, 0xfe, 0xc5, 0xe9, 0x18, 0xb7, 0xfd, 0x62, 0x1e, 0xb7, 0xe5, 0x63, 0x38, 0xc5, 0xfb, 0xff, 0x71, 0xd9, @@ -2086,18 +2086,18 @@ var detailedTests = []detailedTest{ 0xe9, 0x91, 0x94, 0xaa, 0x69, 0x27, 0xaf, 0xf2, 0x54, 0x16, 0xec, 0x48, 0x9d, 0x45, 0x3a, 0x80, 0x7e, 0x03, 0xc0, 0x83, - btcscript.OP_HASH160, btcscript.OP_DATA_20, + txscript.OP_HASH160, txscript.OP_DATA_20, 0x8b, 0xfa, 0x5c, 0x1f, 0x68, 0x5f, 0x13, 0x86, 0x3e, 0x74, 0x2e, 0x1b, 0xaf, 0x15, 0xf1, 0x71, 0xad, 0x49, 0x8b, 0x8f, - btcscript.OP_EQUALVERIFY}, + txscript.OP_EQUALVERIFY}, after: [][]byte{}, disassembly: "040fa492e359dee84b53fec5e918b7fd621eb7e56338c5fbff71d91d1722da58f10f9e8f412f399cb30670a727e99194aa6927aff25416ec489d453a807e03c083 OP_HASH160 8bfa5c1f685f13863e742e1baf15f171ad498b8f OP_EQUALVERIFY", }, { name: "op_hash160 no args", - script: []byte{btcscript.OP_HASH160}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_HASH160}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_HASH160", }, // hash256 test taken from spend of: @@ -2113,7 +2113,7 @@ var detailedTests = []detailedTest{ 0xc8, 0x1b, 0xc3, 0x88, 0x8a, 0x51, 0x32, 0x3a, 0x9f, 0xb8, 0xaa, 0x4b, 0x1e, 0x5e, 0x4a, 0x29, 0xab, 0x5f, 0x49, 0xff, 0xff, 0x00, 0x1d, 0x1d, 0xac, 0x2b, 0x7c}}, - script: []byte{btcscript.OP_HASH256}, + script: []byte{txscript.OP_HASH256}, after: [][]byte{{0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72, 0xc1, 0xa6, 0xa2, 0x46, 0xae, 0x63, 0xf7, 0x4f, 0x93, 0x1e, 0x83, 0x65, 0xe1, 0x5a, 0x08, 0x9c, 0x68, 0xd6, 0x19, @@ -2122,8 +2122,8 @@ var detailedTests = []detailedTest{ }, { name: "OP_HASH256 no args", - script: []byte{btcscript.OP_HASH256}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_HASH256}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_HASH256", }, // We need a more involved setup to test OP_CHECKSIG and @@ -2131,69 +2131,69 @@ var detailedTests = []detailedTest{ // invalid arguments here quite easily. { name: "OP_CHECKSIG one arg", - script: []byte{btcscript.OP_1, btcscript.OP_CHECKSIG}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_1, txscript.OP_CHECKSIG}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "1 OP_CHECKSIG", nSigOps: 1, nPreciseSigOps: 1, }, { name: "OP_CHECKSIG no arg", - script: []byte{btcscript.OP_CHECKSIG}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_CHECKSIG}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_CHECKSIG", nSigOps: 1, nPreciseSigOps: 1, }, { name: "OP_CHECKSIGVERIFY one arg", - script: []byte{btcscript.OP_1, - btcscript.OP_CHECKSIGVERIFY}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_1, + txscript.OP_CHECKSIGVERIFY}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "1 OP_CHECKSIGVERIFY", nSigOps: 1, nPreciseSigOps: 1, }, { name: "OP_CHECKSIGVERIFY no arg", - script: []byte{btcscript.OP_CHECKSIGVERIFY}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_CHECKSIGVERIFY}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_CHECKSIGVERIFY", nSigOps: 1, nPreciseSigOps: 1, }, { name: "OP_CHECKMULTISIG no args", - script: []byte{btcscript.OP_CHECKMULTISIG}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_CHECKMULTISIG}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 20, }, { name: "OP_CHECKMULTISIG huge number", - script: []byte{btcscript.OP_PUSHDATA1, + script: []byte{txscript.OP_PUSHDATA1, 0x9, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, - btcscript.OP_CHECKMULTISIG}, - expectedReturn: btcscript.ErrStackNumberTooBig, + txscript.OP_CHECKMULTISIG}, + expectedReturn: txscript.ErrStackNumberTooBig, disassembly: "010203040506070809 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 20, }, { name: "OP_CHECKMULTISIG too many keys", - script: []byte{btcscript.OP_DATA_1, 21, - btcscript.OP_CHECKMULTISIG}, - expectedReturn: btcscript.ErrStackTooManyPubkeys, + script: []byte{txscript.OP_DATA_1, 21, + txscript.OP_CHECKMULTISIG}, + expectedReturn: txscript.ErrStackTooManyPubkeys, disassembly: "15 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 20, }, { name: "OP_CHECKMULTISIG lying about pubkeys", - script: []byte{btcscript.OP_1, - btcscript.OP_CHECKMULTISIG}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_1, + txscript.OP_CHECKMULTISIG}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "1 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 1, @@ -2202,7 +2202,7 @@ var detailedTests = []detailedTest{ // pubkey comes from blockchain name: "OP_CHECKMULTISIG no sigs", script: []byte{ - btcscript.OP_DATA_65, + txscript.OP_DATA_65, 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, @@ -2211,9 +2211,9 @@ var detailedTests = []detailedTest{ 0x21, 0xc1, 0xb7, 0x30, 0x3b, 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, - btcscript.OP_1, - btcscript.OP_CHECKMULTISIG}, - expectedReturn: btcscript.ErrStackUnderflow, + txscript.OP_1, + txscript.OP_CHECKMULTISIG}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c 1 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 1, @@ -2222,9 +2222,9 @@ var detailedTests = []detailedTest{ // pubkey comes from blockchain name: "OP_CHECKMULTISIG sigs huge no", script: []byte{ - btcscript.OP_PUSHDATA1, + txscript.OP_PUSHDATA1, 0x9, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, - btcscript.OP_DATA_65, + txscript.OP_DATA_65, 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, @@ -2233,17 +2233,17 @@ var detailedTests = []detailedTest{ 0x21, 0xc1, 0xb7, 0x30, 0x3b, 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, - btcscript.OP_1, - btcscript.OP_CHECKMULTISIG}, - expectedReturn: btcscript.ErrStackNumberTooBig, + txscript.OP_1, + txscript.OP_CHECKMULTISIG}, + expectedReturn: txscript.ErrStackNumberTooBig, disassembly: "010203040506070809 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c 1 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 1, }, { name: "OP_CHECKMULTISIG too few sigs", - script: []byte{btcscript.OP_1, - btcscript.OP_DATA_65, + script: []byte{txscript.OP_1, + txscript.OP_DATA_65, 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, @@ -2252,9 +2252,9 @@ var detailedTests = []detailedTest{ 0x21, 0xc1, 0xb7, 0x30, 0x3b, 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, - btcscript.OP_1, - btcscript.OP_CHECKMULTISIG}, - expectedReturn: btcscript.ErrStackUnderflow, + txscript.OP_1, + txscript.OP_CHECKMULTISIG}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c 1 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 1, @@ -2262,8 +2262,8 @@ var detailedTests = []detailedTest{ { // pubkey and sig comes from blockchain, are unrelated name: "OP_CHECKMULTISIG won't verify", - script: []byte{btcscript.OP_1, - btcscript.OP_DATA_71, + script: []byte{txscript.OP_1, + txscript.OP_DATA_71, 0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69, 0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1, 0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6, 0x24, @@ -2272,8 +2272,8 @@ var detailedTests = []detailedTest{ 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90, 0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22, 0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09, 0x01, - btcscript.OP_1, - btcscript.OP_DATA_65, + txscript.OP_1, + txscript.OP_DATA_65, 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, @@ -2282,8 +2282,8 @@ var detailedTests = []detailedTest{ 0x21, 0xc1, 0xb7, 0x30, 0x3b, 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, - btcscript.OP_1, - btcscript.OP_CHECKMULTISIG}, + txscript.OP_1, + txscript.OP_CHECKMULTISIG}, after: [][]byte{{0}}, disassembly: "1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c 1 OP_CHECKMULTISIG", nSigOps: 20, @@ -2294,8 +2294,8 @@ var detailedTests = []detailedTest{ // error. There are pubkeys in the blockchain that don't // parse with any validity. name: "OP_CHECKMULTISIG sigs bad pubkey", - script: []byte{btcscript.OP_1, - btcscript.OP_DATA_71, + script: []byte{txscript.OP_1, + txscript.OP_DATA_71, 0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69, 0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1, 0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6, 0x24, @@ -2304,9 +2304,9 @@ var detailedTests = []detailedTest{ 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90, 0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22, 0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09, 0x01, - btcscript.OP_1, - btcscript.OP_1, btcscript.OP_1, - btcscript.OP_CHECKMULTISIG}, + txscript.OP_1, + txscript.OP_1, txscript.OP_1, + txscript.OP_CHECKMULTISIG}, after: [][]byte{{0}}, disassembly: "1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 1 1 1 OP_CHECKMULTISIG", nSigOps: 20, @@ -2316,36 +2316,36 @@ var detailedTests = []detailedTest{ // disabled opcodes { name: "OP_CHECKMULTISIGVERIFY no args", - script: []byte{btcscript.OP_CHECKMULTISIGVERIFY}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_CHECKMULTISIGVERIFY}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "OP_CHECKMULTISIGVERIFY", nSigOps: 20, nPreciseSigOps: 20, }, { name: "OP_CHECKMULTISIGVERIFY huge number", - script: []byte{btcscript.OP_PUSHDATA1, + script: []byte{txscript.OP_PUSHDATA1, 0x9, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, - btcscript.OP_CHECKMULTISIGVERIFY}, - expectedReturn: btcscript.ErrStackNumberTooBig, + txscript.OP_CHECKMULTISIGVERIFY}, + expectedReturn: txscript.ErrStackNumberTooBig, disassembly: "010203040506070809 OP_CHECKMULTISIGVERIFY", nSigOps: 20, nPreciseSigOps: 20, }, { name: "OP_CHECKMULTISIGVERIFY too many keys", - script: []byte{btcscript.OP_DATA_1, 21, - btcscript.OP_CHECKMULTISIGVERIFY}, - expectedReturn: btcscript.ErrStackTooManyPubkeys, + script: []byte{txscript.OP_DATA_1, 21, + txscript.OP_CHECKMULTISIGVERIFY}, + expectedReturn: txscript.ErrStackTooManyPubkeys, disassembly: "15 OP_CHECKMULTISIGVERIFY", nSigOps: 20, nPreciseSigOps: 20, }, { name: "OP_CHECKMULTISIGVERIFY lying about pubkeys", - script: []byte{btcscript.OP_1, - btcscript.OP_CHECKMULTISIGVERIFY}, - expectedReturn: btcscript.ErrStackUnderflow, + script: []byte{txscript.OP_1, + txscript.OP_CHECKMULTISIGVERIFY}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "1 OP_CHECKMULTISIGVERIFY", nSigOps: 20, nPreciseSigOps: 1, @@ -2354,7 +2354,7 @@ var detailedTests = []detailedTest{ // pubkey comes from blockchain name: "OP_CHECKMULTISIGVERIFY no sigs", script: []byte{ - btcscript.OP_DATA_65, + txscript.OP_DATA_65, 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, @@ -2363,9 +2363,9 @@ var detailedTests = []detailedTest{ 0x21, 0xc1, 0xb7, 0x30, 0x3b, 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, - btcscript.OP_1, - btcscript.OP_CHECKMULTISIGVERIFY}, - expectedReturn: btcscript.ErrStackUnderflow, + txscript.OP_1, + txscript.OP_CHECKMULTISIGVERIFY}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c 1 OP_CHECKMULTISIGVERIFY", nSigOps: 20, nPreciseSigOps: 1, @@ -2373,9 +2373,9 @@ var detailedTests = []detailedTest{ { name: "OP_CHECKMULTISIGVERIFY sigs huge no", script: []byte{ - btcscript.OP_PUSHDATA1, + txscript.OP_PUSHDATA1, 0x9, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, - btcscript.OP_DATA_65, + txscript.OP_DATA_65, 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, @@ -2384,17 +2384,17 @@ var detailedTests = []detailedTest{ 0x21, 0xc1, 0xb7, 0x30, 0x3b, 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, - btcscript.OP_1, - btcscript.OP_CHECKMULTISIGVERIFY}, - expectedReturn: btcscript.ErrStackNumberTooBig, + txscript.OP_1, + txscript.OP_CHECKMULTISIGVERIFY}, + expectedReturn: txscript.ErrStackNumberTooBig, disassembly: "010203040506070809 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c 1 OP_CHECKMULTISIGVERIFY", nSigOps: 20, nPreciseSigOps: 1, }, { name: "OP_CHECKMULTISIGVERIFY too few sigs", - script: []byte{btcscript.OP_1, - btcscript.OP_DATA_65, + script: []byte{txscript.OP_1, + txscript.OP_DATA_65, 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, @@ -2403,9 +2403,9 @@ var detailedTests = []detailedTest{ 0x21, 0xc1, 0xb7, 0x30, 0x3b, 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, - btcscript.OP_1, - btcscript.OP_CHECKMULTISIGVERIFY}, - expectedReturn: btcscript.ErrStackUnderflow, + txscript.OP_1, + txscript.OP_CHECKMULTISIGVERIFY}, + expectedReturn: txscript.ErrStackUnderflow, disassembly: "1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c 1 OP_CHECKMULTISIGVERIFY", nSigOps: 20, nPreciseSigOps: 1, @@ -2413,8 +2413,8 @@ var detailedTests = []detailedTest{ { // pubkey and sig comes from blockchain, are unrelated name: "OP_CHECKMULTISIGVERIFY won't verify", - script: []byte{btcscript.OP_1, - btcscript.OP_DATA_71, + script: []byte{txscript.OP_1, + txscript.OP_DATA_71, 0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69, 0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1, 0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6, 0x24, @@ -2423,8 +2423,8 @@ var detailedTests = []detailedTest{ 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90, 0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22, 0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09, 0x01, - btcscript.OP_1, - btcscript.OP_DATA_65, + txscript.OP_1, + txscript.OP_DATA_65, 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, @@ -2433,9 +2433,9 @@ var detailedTests = []detailedTest{ 0x21, 0xc1, 0xb7, 0x30, 0x3b, 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, - btcscript.OP_1, - btcscript.OP_CHECKMULTISIGVERIFY}, - expectedReturn: btcscript.ErrStackVerifyFailed, + txscript.OP_1, + txscript.OP_CHECKMULTISIGVERIFY}, + expectedReturn: txscript.ErrStackVerifyFailed, disassembly: "1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c 1 OP_CHECKMULTISIGVERIFY", nSigOps: 20, nPreciseSigOps: 1, @@ -2445,8 +2445,8 @@ var detailedTests = []detailedTest{ // error. There are pubkeys in the blockchain that don't // parse with any validity. name: "OP_CHECKMULTISIGVERIFY sigs bad pubkey", - script: []byte{btcscript.OP_1, - btcscript.OP_DATA_71, + script: []byte{txscript.OP_1, + txscript.OP_DATA_71, 0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69, 0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1, 0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6, 0x24, @@ -2455,10 +2455,10 @@ var detailedTests = []detailedTest{ 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90, 0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22, 0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09, 0x01, - btcscript.OP_1, - btcscript.OP_1, btcscript.OP_1, - btcscript.OP_CHECKMULTISIGVERIFY}, - expectedReturn: btcscript.ErrStackVerifyFailed, + txscript.OP_1, + txscript.OP_1, txscript.OP_1, + txscript.OP_CHECKMULTISIGVERIFY}, + expectedReturn: txscript.ErrStackVerifyFailed, disassembly: "1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 1 1 1 OP_CHECKMULTISIGVERIFY", nSigOps: 20, nPreciseSigOps: 1, @@ -2466,208 +2466,208 @@ var detailedTests = []detailedTest{ { // 201 operations + one push, should just fit limits name: "max operations", - script: []byte{btcscript.OP_1, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, + script: []byte{txscript.OP_1, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, }, after: [][]byte{{1}, {1}}, disassembly: "1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP", @@ -2675,425 +2675,425 @@ var detailedTests = []detailedTest{ { // 202 operations + one push name: "too many operations", - script: []byte{btcscript.OP_1, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, + script: []byte{txscript.OP_1, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, }, - expectedReturn: btcscript.ErrStackTooManyOperations, + expectedReturn: txscript.ErrStackTooManyOperations, disassembly: "1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP", }, { // 202 operations + one push name: "too many operations multisig", - script: []byte{btcscript.OP_1, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_DUP, - btcscript.OP_DROP, - btcscript.OP_1, - btcscript.OP_1, - btcscript.OP_1, - btcscript.OP_1, - btcscript.OP_2, - btcscript.OP_CHECKMULTISIG, + script: []byte{txscript.OP_1, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_DUP, + txscript.OP_DROP, + txscript.OP_1, + txscript.OP_1, + txscript.OP_1, + txscript.OP_1, + txscript.OP_2, + txscript.OP_CHECKMULTISIG, }, - expectedReturn: btcscript.ErrStackTooManyOperations, + expectedReturn: txscript.ErrStackTooManyOperations, disassembly: "1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP 1 1 1 1 2 OP_CHECKMULTISIG", nSigOps: 20, nPreciseSigOps: 2, @@ -3102,7 +3102,7 @@ var detailedTests = []detailedTest{ name: "push largest", // 521 bytes before: [][]byte{}, - script: []byte{btcscript.OP_PUSHDATA2, 0x08, 0x02, + script: []byte{txscript.OP_PUSHDATA2, 0x08, 0x02, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, @@ -3225,7 +3225,7 @@ var detailedTests = []detailedTest{ { name: "push too large", // 521 bytes - script: []byte{btcscript.OP_PUSHDATA2, 0x09, 0x02, + script: []byte{txscript.OP_PUSHDATA2, 0x09, 0x02, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, @@ -3284,966 +3284,966 @@ var detailedTests = []detailedTest{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, - expectedReturn: btcscript.ErrStackElementTooBig, + expectedReturn: txscript.ErrStackElementTooBig, // element too big is a parse error. disassembly: "0102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708090102030405060708", }, { name: "OP_CAT disabled", - script: []byte{btcscript.OP_CAT}, - expectedReturn: btcscript.ErrStackOpDisabled, + script: []byte{txscript.OP_CAT}, + expectedReturn: txscript.ErrStackOpDisabled, disassembly: "OP_CAT", }, { name: "OP_SUBSTR disabled", - script: []byte{btcscript.OP_SUBSTR}, - expectedReturn: btcscript.ErrStackOpDisabled, + script: []byte{txscript.OP_SUBSTR}, + expectedReturn: txscript.ErrStackOpDisabled, disassembly: "OP_SUBSTR", }, { name: "OP_LEFT disabled", - script: []byte{btcscript.OP_LEFT}, - expectedReturn: btcscript.ErrStackOpDisabled, + script: []byte{txscript.OP_LEFT}, + expectedReturn: txscript.ErrStackOpDisabled, disassembly: "OP_LEFT", }, { name: "OP_RIGHT disabled", - script: []byte{btcscript.OP_RIGHT}, - expectedReturn: btcscript.ErrStackOpDisabled, + script: []byte{txscript.OP_RIGHT}, + expectedReturn: txscript.ErrStackOpDisabled, disassembly: "OP_RIGHT", }, { name: "OP_INVERT disabled", - script: []byte{btcscript.OP_INVERT}, - expectedReturn: btcscript.ErrStackOpDisabled, + script: []byte{txscript.OP_INVERT}, + expectedReturn: txscript.ErrStackOpDisabled, disassembly: "OP_INVERT", }, { name: "OP_AND disabled", - script: []byte{btcscript.OP_AND}, - expectedReturn: btcscript.ErrStackOpDisabled, + script: []byte{txscript.OP_AND}, + expectedReturn: txscript.ErrStackOpDisabled, disassembly: "OP_AND", }, { name: "OP_OR disabled", - script: []byte{btcscript.OP_OR}, - expectedReturn: btcscript.ErrStackOpDisabled, + script: []byte{txscript.OP_OR}, + expectedReturn: txscript.ErrStackOpDisabled, disassembly: "OP_OR", }, { name: "OP_XOR disabled", - script: []byte{btcscript.OP_XOR}, - expectedReturn: btcscript.ErrStackOpDisabled, + script: []byte{txscript.OP_XOR}, + expectedReturn: txscript.ErrStackOpDisabled, disassembly: "OP_XOR", }, { name: "OP_2MUL disabled", - script: []byte{btcscript.OP_2MUL}, - expectedReturn: btcscript.ErrStackOpDisabled, + script: []byte{txscript.OP_2MUL}, + expectedReturn: txscript.ErrStackOpDisabled, disassembly: "OP_2MUL", }, { name: "OP_2DIV disabled", - script: []byte{btcscript.OP_2DIV}, - expectedReturn: btcscript.ErrStackOpDisabled, + script: []byte{txscript.OP_2DIV}, + expectedReturn: txscript.ErrStackOpDisabled, disassembly: "OP_2DIV", }, { name: "OP_2DIV disabled", - script: []byte{btcscript.OP_2DIV}, - expectedReturn: btcscript.ErrStackOpDisabled, + script: []byte{txscript.OP_2DIV}, + expectedReturn: txscript.ErrStackOpDisabled, disassembly: "OP_2DIV", }, { name: "OP_MUL disabled", - script: []byte{btcscript.OP_MUL}, - expectedReturn: btcscript.ErrStackOpDisabled, + script: []byte{txscript.OP_MUL}, + expectedReturn: txscript.ErrStackOpDisabled, disassembly: "OP_MUL", }, { name: "OP_DIV disabled", - script: []byte{btcscript.OP_DIV}, - expectedReturn: btcscript.ErrStackOpDisabled, + script: []byte{txscript.OP_DIV}, + expectedReturn: txscript.ErrStackOpDisabled, disassembly: "OP_DIV", }, { name: "OP_MOD disabled", - script: []byte{btcscript.OP_MOD}, - expectedReturn: btcscript.ErrStackOpDisabled, + script: []byte{txscript.OP_MOD}, + expectedReturn: txscript.ErrStackOpDisabled, disassembly: "OP_MOD", }, { name: "OP_LSHIFT disabled", - script: []byte{btcscript.OP_LSHIFT}, - expectedReturn: btcscript.ErrStackOpDisabled, + script: []byte{txscript.OP_LSHIFT}, + expectedReturn: txscript.ErrStackOpDisabled, disassembly: "OP_LSHIFT", }, { name: "OP_RSHIFT disabled", - script: []byte{btcscript.OP_RSHIFT}, - expectedReturn: btcscript.ErrStackOpDisabled, + script: []byte{txscript.OP_RSHIFT}, + expectedReturn: txscript.ErrStackOpDisabled, disassembly: "OP_RSHIFT", }, // Reserved opcodes { name: "OP_RESERVED reserved", - script: []byte{btcscript.OP_RESERVED}, - expectedReturn: btcscript.ErrStackReservedOpcode, + script: []byte{txscript.OP_RESERVED}, + expectedReturn: txscript.ErrStackReservedOpcode, disassembly: "OP_RESERVED", }, { name: "OP_VER reserved", - script: []byte{btcscript.OP_VER}, - expectedReturn: btcscript.ErrStackReservedOpcode, + script: []byte{txscript.OP_VER}, + expectedReturn: txscript.ErrStackReservedOpcode, disassembly: "OP_VER", }, { name: "OP_VERIF reserved", - script: []byte{btcscript.OP_VERIF}, - expectedReturn: btcscript.ErrStackReservedOpcode, + script: []byte{txscript.OP_VERIF}, + expectedReturn: txscript.ErrStackReservedOpcode, disassembly: "OP_VERIF", }, { name: "OP_VERNOTIF reserved", - script: []byte{btcscript.OP_VERNOTIF}, - expectedReturn: btcscript.ErrStackReservedOpcode, + script: []byte{txscript.OP_VERNOTIF}, + expectedReturn: txscript.ErrStackReservedOpcode, disassembly: "OP_VERNOTIF", }, { name: "OP_RESERVED1 reserved", - script: []byte{btcscript.OP_RESERVED1}, - expectedReturn: btcscript.ErrStackReservedOpcode, + script: []byte{txscript.OP_RESERVED1}, + expectedReturn: txscript.ErrStackReservedOpcode, disassembly: "OP_RESERVED1", }, { name: "OP_RESERVED2 reserved", - script: []byte{btcscript.OP_RESERVED2}, - expectedReturn: btcscript.ErrStackReservedOpcode, + script: []byte{txscript.OP_RESERVED2}, + expectedReturn: txscript.ErrStackReservedOpcode, disassembly: "OP_RESERVED2", }, // Invalid Opcodes { name: "invalid opcode 186", - script: []byte{btcscript.OP_UNKNOWN186}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN186}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN186", }, { name: "invalid opcode 187", - script: []byte{btcscript.OP_UNKNOWN187}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN187}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN187", }, { name: "invalid opcode 188", - script: []byte{btcscript.OP_UNKNOWN188}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN188}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN188", }, { name: "invalid opcode 189", - script: []byte{btcscript.OP_UNKNOWN189}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN189}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN189", }, { name: "invalid opcode 190", - script: []byte{btcscript.OP_UNKNOWN190}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN190}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN190", }, { name: "invalid opcode 191", - script: []byte{btcscript.OP_UNKNOWN191}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN191}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN191", }, { name: "invalid opcode 192", - script: []byte{btcscript.OP_UNKNOWN192}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN192}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN192", }, { name: "invalid opcode 193", - script: []byte{btcscript.OP_UNKNOWN193}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN193}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN193", }, { name: "invalid opcode 194", - script: []byte{btcscript.OP_UNKNOWN194}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN194}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN194", }, { name: "invalid opcode 195", - script: []byte{btcscript.OP_UNKNOWN195}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN195}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN195", }, { name: "invalid opcode 196", - script: []byte{btcscript.OP_UNKNOWN196}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN196}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN196", }, { name: "invalid opcode 197", - script: []byte{btcscript.OP_UNKNOWN197}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN197}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN197", }, { name: "invalid opcode 198", - script: []byte{btcscript.OP_UNKNOWN198}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN198}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN198", }, { name: "invalid opcode 199", - script: []byte{btcscript.OP_UNKNOWN199}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN199}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN199", }, { name: "invalid opcode 200", - script: []byte{btcscript.OP_UNKNOWN200}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN200}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN200", }, { name: "invalid opcode 201", - script: []byte{btcscript.OP_UNKNOWN201}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN201}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN201", }, { name: "invalid opcode 202", - script: []byte{btcscript.OP_UNKNOWN202}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN202}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN202", }, { name: "invalid opcode 203", - script: []byte{btcscript.OP_UNKNOWN203}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN203}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN203", }, { name: "invalid opcode 204", - script: []byte{btcscript.OP_UNKNOWN204}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN204}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN204", }, { name: "invalid opcode 205", - script: []byte{btcscript.OP_UNKNOWN205}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN205}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN205", }, { name: "invalid opcode 206", - script: []byte{btcscript.OP_UNKNOWN206}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN206}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN206", }, { name: "invalid opcode 207", - script: []byte{btcscript.OP_UNKNOWN207}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN207}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN207", }, { name: "invalid opcode 208", - script: []byte{btcscript.OP_UNKNOWN208}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN208}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN208", }, { name: "invalid opcode 209", - script: []byte{btcscript.OP_UNKNOWN209}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN209}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN209", }, { name: "invalid opcode 210", - script: []byte{btcscript.OP_UNKNOWN210}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN210}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN210", }, { name: "invalid opcode 211", - script: []byte{btcscript.OP_UNKNOWN211}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN211}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN211", }, { name: "invalid opcode 212", - script: []byte{btcscript.OP_UNKNOWN212}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN212}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN212", }, { name: "invalid opcode 213", - script: []byte{btcscript.OP_UNKNOWN213}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN213}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN213", }, { name: "invalid opcode 214", - script: []byte{btcscript.OP_UNKNOWN214}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN214}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN214", }, { name: "invalid opcode 215", - script: []byte{btcscript.OP_UNKNOWN215}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN215}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN215", }, { name: "invalid opcode 216", - script: []byte{btcscript.OP_UNKNOWN216}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN216}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN216", }, { name: "invalid opcode 217", - script: []byte{btcscript.OP_UNKNOWN217}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN217}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN217", }, { name: "invalid opcode 218", - script: []byte{btcscript.OP_UNKNOWN218}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN218}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN218", }, { name: "invalid opcode 219", - script: []byte{btcscript.OP_UNKNOWN219}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN219}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN219", }, { name: "invalid opcode 220", - script: []byte{btcscript.OP_UNKNOWN220}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN220}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN220", }, { name: "invalid opcode 221", - script: []byte{btcscript.OP_UNKNOWN221}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN221}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN221", }, { name: "invalid opcode 222", - script: []byte{btcscript.OP_UNKNOWN222}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN222}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN222", }, { name: "invalid opcode 223", - script: []byte{btcscript.OP_UNKNOWN223}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN223}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN223", }, { name: "invalid opcode 224", - script: []byte{btcscript.OP_UNKNOWN224}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN224}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN224", }, { name: "invalid opcode 225", - script: []byte{btcscript.OP_UNKNOWN225}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN225}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN225", }, { name: "invalid opcode 226", - script: []byte{btcscript.OP_UNKNOWN226}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN226}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN226", }, { name: "invalid opcode 227", - script: []byte{btcscript.OP_UNKNOWN227}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN227}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN227", }, { name: "invalid opcode 228", - script: []byte{btcscript.OP_UNKNOWN228}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN228}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN228", }, { name: "invalid opcode 229", - script: []byte{btcscript.OP_UNKNOWN229}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN229}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN229", }, { name: "invalid opcode 230", - script: []byte{btcscript.OP_UNKNOWN230}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN230}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN230", }, { name: "invalid opcode 231", - script: []byte{btcscript.OP_UNKNOWN231}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN231}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN231", }, { name: "invalid opcode 232", - script: []byte{btcscript.OP_UNKNOWN232}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN232}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN232", }, { name: "invalid opcode 233", - script: []byte{btcscript.OP_UNKNOWN233}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN233}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN233", }, { name: "invalid opcode 234", - script: []byte{btcscript.OP_UNKNOWN234}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN234}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN234", }, { name: "invalid opcode 235", - script: []byte{btcscript.OP_UNKNOWN235}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN235}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN235", }, { name: "invalid opcode 236", - script: []byte{btcscript.OP_UNKNOWN236}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN236}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN236", }, { name: "invalid opcode 237", - script: []byte{btcscript.OP_UNKNOWN237}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN237}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN237", }, { name: "invalid opcode 238", - script: []byte{btcscript.OP_UNKNOWN238}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN238}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN238", }, { name: "invalid opcode 239", - script: []byte{btcscript.OP_UNKNOWN239}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN239}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN239", }, { name: "invalid opcode 240", - script: []byte{btcscript.OP_UNKNOWN240}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN240}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN240", }, { name: "invalid opcode 241", - script: []byte{btcscript.OP_UNKNOWN241}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN241}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN241", }, { name: "invalid opcode 242", - script: []byte{btcscript.OP_UNKNOWN242}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN242}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN242", }, { name: "invalid opcode 243", - script: []byte{btcscript.OP_UNKNOWN243}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN243}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN243", }, { name: "invalid opcode 244", - script: []byte{btcscript.OP_UNKNOWN244}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN244}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN244", }, { name: "invalid opcode 245", - script: []byte{btcscript.OP_UNKNOWN245}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN245}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN245", }, { name: "invalid opcode 246", - script: []byte{btcscript.OP_UNKNOWN246}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN246}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN246", }, { name: "invalid opcode 247", - script: []byte{btcscript.OP_UNKNOWN247}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN247}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN247", }, { name: "invalid opcode 248", - script: []byte{btcscript.OP_UNKNOWN248}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN248}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN248", }, { name: "invalid opcode 249", - script: []byte{btcscript.OP_UNKNOWN249}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN249}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN249", }, { name: "invalid opcode 250", - script: []byte{btcscript.OP_UNKNOWN250}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN250}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN250", }, { name: "invalid opcode 251", - script: []byte{btcscript.OP_UNKNOWN251}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN251}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN251", }, { name: "invalid opcode 252", - script: []byte{btcscript.OP_UNKNOWN252}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_UNKNOWN252}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_UNKNOWN252", }, { name: "invalid opcode 186 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN186, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN186, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN186 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 187 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN187, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN187, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN187 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 188 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN188, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN188, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN188 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 189 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN189, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN189, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN189 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 190 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN190, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN190, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN190 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 191 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN191, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN191, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN191 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 192 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN192, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN192, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN192 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 193 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN193, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN193, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN193 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 194 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN194, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN194, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN194 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 195 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN195, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN195, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN195 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 196 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN196, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN196, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN196 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 197 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN197, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN197, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN197 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 198 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN198, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN198, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN198 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 199 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN199, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN199, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN199 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 200 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN200, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN200, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN200 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 201 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN201, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN201, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN201 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 202 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN202, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN202, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN202 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 203 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN203, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN203, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN203 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 204 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN204, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN204, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN204 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 205 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN205, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN205, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN205 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 206 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN206, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN206, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN206 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 207 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN207, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN207, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN207 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 208 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN208, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN208, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN208 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 209 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN209, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN209, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN209 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 210 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN210, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN210, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN210 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 211 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN211, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN211, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN211 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 212 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN212, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN212, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN212 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 213 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN213, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN213, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN213 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 214 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN214, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN214, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN214 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 215 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN215, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN215, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN215 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 216 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN216, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN216, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN216 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 217 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN217, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN217, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN217 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 218 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN218, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN218, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN218 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 219 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN219, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN219, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN219 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 220 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN220, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN220, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN220 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 221 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN221, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN221, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN221 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 222 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN222, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN222, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN222 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 223 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN223, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN223, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN223 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 224 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN224, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN224, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN224 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 225 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN225, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN225, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN225 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 226 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN226, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN226, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN226 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 227 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN227, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN227, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN227 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 228 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN228, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN228, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN228 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 229 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN229, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN229, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN229 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 230 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN230, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN230, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN230 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 231 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN231, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN231, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN231 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 232 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN232, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN232, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN232 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 233 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN233, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN233, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN233 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 234 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN234, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN234, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN234 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 235 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN235, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN235, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN235 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 236 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN236, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN236, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN236 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 237 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN237, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN237, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN237 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 238 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN238, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN238, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN238 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 239 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN239, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN239, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN239 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 240 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN240, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN240, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN240 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 241 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN241, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN241, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN241 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 242 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN242, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN242, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN242 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 243 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN243, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN243, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN243 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 244 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN244, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN244, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN244 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 245 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN245, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN245, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN245 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 246 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN246, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN246, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN246 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 247 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN247, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN247, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN247 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 248 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN248, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN248, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN248 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 249 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN249, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN249, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN249 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 250 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN250, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN250, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN250 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 251 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN251, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN251, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN251 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode 252 if noexec", - script: []byte{btcscript.OP_FALSE, btcscript.OP_IF, btcscript.OP_UNKNOWN252, btcscript.OP_ELSE, btcscript.OP_TRUE, btcscript.OP_ENDIF}, + script: []byte{txscript.OP_FALSE, txscript.OP_IF, txscript.OP_UNKNOWN252, txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF}, after: [][]byte{{0x01}}, disassembly: "0 OP_IF OP_UNKNOWN252 OP_ELSE 1 OP_ENDIF", }, { name: "invalid opcode OP_PUBKEY", - script: []byte{btcscript.OP_PUBKEY}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_PUBKEY}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_PUBKEY", }, { name: "invalid opcode OP_PUBKEYHASH", - script: []byte{btcscript.OP_PUBKEYHASH}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_PUBKEYHASH}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_PUBKEYHASH", }, { name: "invalid opcode OP_INVALIDOPCODE", - script: []byte{btcscript.OP_INVALIDOPCODE}, - expectedReturn: btcscript.ErrStackInvalidOpcode, + script: []byte{txscript.OP_INVALIDOPCODE}, + expectedReturn: txscript.ErrStackInvalidOpcode, disassembly: "OP_INVALIDOPCODE", }, } @@ -4286,7 +4286,7 @@ func testOpcode(t *testing.T, test *detailedTest) { tx.TxOut[0].PkScript = test.script - engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript, + engine, err := txscript.NewScript(tx.TxIn[0].SignatureScript, tx.TxOut[0].PkScript, 0, tx, 0) if err != nil { if err != test.expectedReturn { @@ -4321,7 +4321,7 @@ func testOpcode(t *testing.T, test *detailedTest) { test.name, err) } _, err = engine.DisasmScript(2) - if err != btcscript.ErrStackInvalidIndex { + if err != txscript.ErrStackInvalidIndex { t.Errorf("%s: got unexpected error for invalid "+ "disassembly index: \"%v\"", test.name, err) } @@ -4383,7 +4383,7 @@ func TestOpcodes(t *testing.T) { func testDisasmString(t *testing.T, test *detailedTest) { // mock up fake tx. - dis, err := btcscript.DisasmString(test.script) + dis, err := txscript.DisasmString(test.script) if err != nil { if err != test.disassemblyerr { t.Errorf("%s: disassembly got error %v expected %v", test.name, @@ -4421,7 +4421,7 @@ func TestSigOps(t *testing.T) { t.Parallel() for _, test := range detailedTests { - count := btcscript.GetSigOpCount(test.script) + count := txscript.GetSigOpCount(test.script) if count != test.nSigOps { t.Errorf("%s: expected count of %d, got %d", test.name, test.nSigOps, count) @@ -4441,8 +4441,8 @@ func TestPreciseSigOps(t *testing.T) { t.Parallel() for _, test := range detailedTests { - count := btcscript.GetPreciseSigOpCount( - []byte{btcscript.OP_1}, test.script, false) + count := txscript.GetPreciseSigOpCount( + []byte{txscript.OP_1}, test.script, false) if count != test.nPreciseSigOps { t.Errorf("%s: expected count of %d, got %d", test.name, test.nPreciseSigOps, count) diff --git a/script.go b/txscript/script.go similarity index 99% rename from script.go rename to txscript/script.go index 86d71ea9..5aa074b0 100644 --- a/script.go +++ b/txscript/script.go @@ -1,8 +1,8 @@ -// Copyright (c) 2013-2014 Conformal Systems LLC. +// Copyright (c) 2013-2015 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. -package btcscript +package txscript import ( "bytes" @@ -193,7 +193,7 @@ func (t ScriptClass) String() string { return scriptClassToName[t] } -// Script is the virtual machine that executes btcscripts. +// Script is the virtual machine that executes scripts. type Script struct { scripts [][]parsedOpcode scriptidx int diff --git a/script_test.go b/txscript/script_test.go similarity index 83% rename from script_test.go rename to txscript/script_test.go index e8d9c372..b4c7959d 100644 --- a/script_test.go +++ b/txscript/script_test.go @@ -1,8 +1,8 @@ -// Copyright (c) 2013-2014 Conformal Systems LLC. +// Copyright (c) 2013-2015 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. -package btcscript_test +package txscript_test import ( "bytes" @@ -10,9 +10,9 @@ import ( "fmt" "testing" + "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcec" "github.com/btcsuite/btcnet" - "github.com/btcsuite/btcscript" "github.com/btcsuite/btcutil" "github.com/btcsuite/btcwire" ) @@ -21,7 +21,7 @@ import ( // allows access to the script from a known good script built with the builder. // Any errors are converted to a panic since it is only, and must only, be used // with hard coded, and therefore, known good, scripts. -func builderScript(builder *btcscript.ScriptBuilder) []byte { +func builderScript(builder *txscript.ScriptBuilder) []byte { script, err := builder.Script() if err != nil { panic(err) @@ -38,12 +38,12 @@ func TestPushedData(t *testing.T) { valid bool }{ { - []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, + []byte{txscript.OP_0, txscript.OP_IF, txscript.OP_0, txscript.OP_ELSE, txscript.OP_2, txscript.OP_ENDIF}, [][]byte{{}, {}}, true, }, { - builderScript(btcscript.NewScriptBuilder().AddInt64(16777216).AddInt64(10000000)), + builderScript(txscript.NewScriptBuilder().AddInt64(16777216).AddInt64(10000000)), [][]byte{ {0x00, 0x00, 0x00, 0x01}, // 16777216 {0x80, 0x96, 0x98, 0x00}, // 10000000 @@ -51,9 +51,9 @@ func TestPushedData(t *testing.T) { true, }, { - builderScript(btcscript.NewScriptBuilder().AddOp(btcscript.OP_DUP).AddOp(btcscript.OP_HASH160). - AddData([]byte("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem")).AddOp(btcscript.OP_EQUALVERIFY). - AddOp(btcscript.OP_CHECKSIG)), + builderScript(txscript.NewScriptBuilder().AddOp(txscript.OP_DUP).AddOp(txscript.OP_HASH160). + AddData([]byte("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem")).AddOp(txscript.OP_EQUALVERIFY). + AddOp(txscript.OP_CHECKSIG)), [][]byte{ // 17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem { @@ -66,15 +66,15 @@ func TestPushedData(t *testing.T) { true, }, { - builderScript(btcscript.NewScriptBuilder().AddOp(btcscript.OP_PUSHDATA4).AddInt64(1000). - AddOp(btcscript.OP_EQUAL)), + builderScript(txscript.NewScriptBuilder().AddOp(txscript.OP_PUSHDATA4).AddInt64(1000). + AddOp(txscript.OP_EQUAL)), [][]byte{}, false, }, } for x, test := range tests { - pushedData, err := btcscript.PushedData(test.in) + pushedData, err := txscript.PushedData(test.in) if test.valid && err != nil { t.Errorf("TestPushedData failed test #%d: %v\n", x, err) continue @@ -95,35 +95,35 @@ func TestStandardPushes(t *testing.T) { t.Parallel() for i := 0; i < 65535; i++ { - builder := btcscript.NewScriptBuilder() + builder := txscript.NewScriptBuilder() builder.AddInt64(int64(i)) script, err := builder.Script() if err != nil { t.Errorf("StandardPushesTests test #%d unexpected error: %v\n", i, err) continue } - if result := btcscript.IsPushOnlyScript(script); !result { + if result := txscript.IsPushOnlyScript(script); !result { t.Errorf("StandardPushesTests IsPushOnlyScript test #%d failed: %x\n", i, script) continue } - if result := btcscript.HasCanonicalPushes(script); !result { + if result := txscript.HasCanonicalPushes(script); !result { t.Errorf("StandardPushesTests HasCanonicalPushes test #%d failed: %x\n", i, script) continue } } - for i := 0; i <= btcscript.MaxScriptElementSize; i++ { - builder := btcscript.NewScriptBuilder() + for i := 0; i <= txscript.MaxScriptElementSize; i++ { + builder := txscript.NewScriptBuilder() builder.AddData(bytes.Repeat([]byte{0x49}, i)) script, err := builder.Script() if err != nil { t.Errorf("StandardPushesTests test #%d unexpected error: %v\n", i, err) continue } - if result := btcscript.IsPushOnlyScript(script); !result { + if result := txscript.IsPushOnlyScript(script); !result { t.Errorf("StandardPushesTests IsPushOnlyScript test #%d failed: %x\n", i, script) continue } - if result := btcscript.HasCanonicalPushes(script); !result { + if result := txscript.HasCanonicalPushes(script); !result { t.Errorf("StandardPushesTests HasCanonicalPushes test #%d failed: %x\n", i, script) continue } @@ -133,16 +133,16 @@ func TestStandardPushes(t *testing.T) { type txTest struct { name string tx *btcwire.MsgTx - pkScript []byte // output script of previous tx - idx int // tx idx to be run. - bip16 bool // is bip16 active? - canonicalSigs bool // should signatures be validated as canonical? - parseErr error // failure of NewScript - err error // Failure of Executre - shouldFail bool // Execute should fail with nonspecified error. - nSigOps int // result of GetPreciseSigOpsCount - scriptInfo btcscript.ScriptInfo // result of ScriptInfo - scriptInfoErr error // error return of ScriptInfo + pkScript []byte // output script of previous tx + idx int // tx idx to be run. + bip16 bool // is bip16 active? + canonicalSigs bool // should signatures be validated as canonical? + parseErr error // failure of NewScript + err error // Failure of Executre + shouldFail bool // Execute should fail with nonspecified error. + nSigOps int // result of GetPreciseSigOpsCount + scriptInfo txscript.ScriptInfo // result of ScriptInfo + scriptInfoErr error // error return of ScriptInfo } var txTests = []txTest{ @@ -168,7 +168,7 @@ var txTests = []txTest{ Index: 0, }, SignatureScript: []uint8{ - btcscript.OP_DATA_71, + txscript.OP_DATA_71, 0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69, 0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, @@ -193,7 +193,7 @@ var txTests = []txTest{ { Value: 1000000000, PkScript: []byte{ - btcscript.OP_DATA_65, + txscript.OP_DATA_65, 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, 0x90, 0x5f, 0x07, 0xf0, 0x6b, @@ -207,13 +207,13 @@ var txTests = []txTest{ 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, - btcscript.OP_CHECKSIG, + txscript.OP_CHECKSIG, }, }, { Value: 4000000000, PkScript: []byte{ - btcscript.OP_DATA_65, + txscript.OP_DATA_65, 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, @@ -227,14 +227,14 @@ var txTests = []txTest{ 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, 0xa3, - btcscript.OP_CHECKSIG, + txscript.OP_CHECKSIG, }, }, }, LockTime: 0, }, pkScript: []byte{ - btcscript.OP_DATA_65, + txscript.OP_DATA_65, 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 0xd7, @@ -242,12 +242,12 @@ var txTests = []txTest{ 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, - 0x12, 0xa3, btcscript.OP_CHECKSIG, + 0x12, 0xa3, txscript.OP_CHECKSIG, }, idx: 0, nSigOps: 1, - scriptInfo: btcscript.ScriptInfo{ - PkScriptClass: btcscript.PubKeyTy, + scriptInfo: txscript.ScriptInfo{ + PkScriptClass: txscript.PubKeyTy, NumInputs: 1, ExpectedInputs: 1, SigOps: 1, @@ -274,7 +274,7 @@ var txTests = []txTest{ Index: 0, }, SignatureScript: []uint8{ - btcscript.OP_DATA_71, + txscript.OP_DATA_71, 0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69, 0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, @@ -299,7 +299,7 @@ var txTests = []txTest{ { Value: 1000000000, PkScript: []byte{ - btcscript.OP_DATA_65, + txscript.OP_DATA_65, 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, 0x90, 0x5f, 0x07, 0xf0, 0x6b, @@ -313,13 +313,13 @@ var txTests = []txTest{ 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, - btcscript.OP_CHECKSIG, + txscript.OP_CHECKSIG, }, }, { Value: 5000000000, PkScript: []byte{ - btcscript.OP_DATA_65, + txscript.OP_DATA_65, 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, @@ -333,14 +333,14 @@ var txTests = []txTest{ 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, 0xa3, - btcscript.OP_CHECKSIG, + txscript.OP_CHECKSIG, }, }, }, LockTime: 0, }, pkScript: []byte{ - btcscript.OP_DATA_65, + txscript.OP_DATA_65, 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 0xd7, @@ -348,13 +348,13 @@ var txTests = []txTest{ 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, - 0x12, 0xa3, btcscript.OP_CHECKSIG, + 0x12, 0xa3, txscript.OP_CHECKSIG, }, idx: 0, - err: btcscript.ErrStackScriptFailed, + err: txscript.ErrStackScriptFailed, nSigOps: 1, - scriptInfo: btcscript.ScriptInfo{ - PkScriptClass: btcscript.PubKeyTy, + scriptInfo: txscript.ScriptInfo{ + PkScriptClass: txscript.PubKeyTy, NumInputs: 1, ExpectedInputs: 1, SigOps: 1, @@ -382,7 +382,7 @@ var txTests = []txTest{ // Signature has length fiddled to // fail parsing. SignatureScript: []uint8{ - btcscript.OP_DATA_71, + txscript.OP_DATA_71, 0x30, 0x45, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69, 0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, @@ -407,7 +407,7 @@ var txTests = []txTest{ { Value: 1000000000, PkScript: []byte{ - btcscript.OP_DATA_65, + txscript.OP_DATA_65, 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, 0x90, 0x5f, 0x07, 0xf0, 0x6b, @@ -421,13 +421,13 @@ var txTests = []txTest{ 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, - btcscript.OP_CHECKSIG, + txscript.OP_CHECKSIG, }, }, { Value: 4000000000, PkScript: []byte{ - btcscript.OP_DATA_65, + txscript.OP_DATA_65, 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, @@ -441,14 +441,14 @@ var txTests = []txTest{ 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, 0xa3, - btcscript.OP_CHECKSIG, + txscript.OP_CHECKSIG, }, }, }, LockTime: 0, }, pkScript: []byte{ - btcscript.OP_DATA_65, + txscript.OP_DATA_65, 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 0xd7, @@ -456,13 +456,13 @@ var txTests = []txTest{ 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, - 0x12, 0xa3, btcscript.OP_CHECKSIG, + 0x12, 0xa3, txscript.OP_CHECKSIG, }, idx: 0, shouldFail: true, nSigOps: 1, - scriptInfo: btcscript.ScriptInfo{ - PkScriptClass: btcscript.PubKeyTy, + scriptInfo: txscript.ScriptInfo{ + PkScriptClass: txscript.PubKeyTy, NumInputs: 1, ExpectedInputs: 1, SigOps: 1, @@ -488,7 +488,7 @@ var txTests = []txTest{ Index: 0, }, SignatureScript: []uint8{ - btcscript.OP_DATA_71, + txscript.OP_DATA_71, 0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69, 0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, @@ -513,7 +513,7 @@ var txTests = []txTest{ { Value: 1000000000, PkScript: []byte{ - btcscript.OP_DATA_65, + txscript.OP_DATA_65, 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, 0x90, 0x5f, 0x07, 0xf0, 0x6b, @@ -527,13 +527,13 @@ var txTests = []txTest{ 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, - btcscript.OP_CHECKSIG, + txscript.OP_CHECKSIG, }, }, { Value: 4000000000, PkScript: []byte{ - btcscript.OP_DATA_65, + txscript.OP_DATA_65, 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, @@ -547,7 +547,7 @@ var txTests = []txTest{ 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, 0xa3, - btcscript.OP_CHECKSIG, + txscript.OP_CHECKSIG, }, }, }, @@ -555,7 +555,7 @@ var txTests = []txTest{ }, // pubkey header magic byte has been changed to parse wrong. pkScript: []byte{ - btcscript.OP_DATA_65, + txscript.OP_DATA_65, 0x02, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 0xd7, @@ -563,13 +563,13 @@ var txTests = []txTest{ 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, - 0x12, 0xa3, btcscript.OP_CHECKSIG, + 0x12, 0xa3, txscript.OP_CHECKSIG, }, idx: 0, shouldFail: true, nSigOps: 1, - scriptInfo: btcscript.ScriptInfo{ - PkScriptClass: btcscript.PubKeyTy, + scriptInfo: txscript.ScriptInfo{ + PkScriptClass: txscript.PubKeyTy, NumInputs: 1, ExpectedInputs: 1, SigOps: 1, @@ -597,7 +597,7 @@ var txTests = []txTest{ Index: 1, }, SignatureScript: []byte{ - btcscript.OP_DATA_71, + txscript.OP_DATA_71, 0x30, 0x44, 0x02, 0x20, 0xbb, 0x4f, 0xbc, 0x49, 0x5a, 0xa2, 0x3b, 0xab, 0xb2, 0xc2, 0xbe, @@ -613,7 +613,7 @@ var txTests = []txTest{ 0x75, 0x67, 0x82, 0xee, 0x6f, 0x8a, 0x22, 0xa9, 0x59, 0xa2, 0x02, - btcscript.OP_DATA_65, + txscript.OP_DATA_65, 0x04, 0xf1, 0x93, 0x9a, 0xe6, 0xb0, 0x1e, 0x84, 0x9b, 0xf0, 0x5d, 0x0e, 0xd5, 0x1f, 0xd5, @@ -635,49 +635,49 @@ var txTests = []txTest{ { Value: 1000000, PkScript: []byte{ - btcscript.OP_DUP, - btcscript.OP_HASH160, - btcscript.OP_DATA_20, + txscript.OP_DUP, + txscript.OP_HASH160, + txscript.OP_DATA_20, 0x66, 0x0d, 0x4e, 0xf3, 0xa7, 0x43, 0xe3, 0xe6, 0x96, 0xad, 0x99, 0x03, 0x64, 0xe5, 0x55, 0xc2, 0x71, 0xad, 0x50, 0x4b, - btcscript.OP_EQUALVERIFY, - btcscript.OP_CHECKSIG, + txscript.OP_EQUALVERIFY, + txscript.OP_CHECKSIG, }, }, { Value: 29913632, PkScript: []byte{ - btcscript.OP_DUP, - btcscript.OP_HASH160, - btcscript.OP_DATA_20, + txscript.OP_DUP, + txscript.OP_HASH160, + txscript.OP_DATA_20, 0x21, 0xc4, 0x3c, 0xe4, 0x00, 0x90, 0x13, 0x12, 0xa6, 0x03, 0xe4, 0x20, 0x7a, 0xad, 0xfd, 0x74, 0x2b, 0xe8, 0xe7, 0xda, - btcscript.OP_EQUALVERIFY, - btcscript.OP_CHECKSIG, + txscript.OP_EQUALVERIFY, + txscript.OP_CHECKSIG, }, }, }, LockTime: 0, }, pkScript: []byte{ - btcscript.OP_DUP, - btcscript.OP_HASH160, - btcscript.OP_DATA_20, + txscript.OP_DUP, + txscript.OP_HASH160, + txscript.OP_DATA_20, 0x21, 0xc4, 0x3c, 0xe4, 0x00, 0x90, 0x13, 0x12, 0xa6, 0x03, 0xe4, 0x20, 0x7a, 0xad, 0xfd, 0x74, 0x2b, 0xe8, 0xe7, 0xda, - btcscript.OP_EQUALVERIFY, - btcscript.OP_CHECKSIG, + txscript.OP_EQUALVERIFY, + txscript.OP_CHECKSIG, }, idx: 0, bip16: true, // after threshold nSigOps: 1, - scriptInfo: btcscript.ScriptInfo{ - PkScriptClass: btcscript.PubKeyHashTy, + scriptInfo: txscript.ScriptInfo{ + PkScriptClass: txscript.PubKeyHashTy, NumInputs: 2, ExpectedInputs: 2, SigOps: 1, @@ -703,7 +703,7 @@ var txTests = []txTest{ Index: 1, }, SignatureScript: []byte{ - btcscript.OP_DATA_71, + txscript.OP_DATA_71, 0x30, 0x44, 0x02, 0x20, 0xa0, 0x42, 0xde, 0xe5, 0x52, 0x6b, 0xf2, 0x29, 0x4d, 0x3f, 0x3e, @@ -719,7 +719,7 @@ var txTests = []txTest{ 0x68, 0x02, 0x6a, 0x97, 0x5c, 0x7d, 0xae, 0x11, 0x2e, 0x4f, 0x01, - btcscript.OP_DATA_65, + txscript.OP_DATA_65, 0x04, 0x49, 0x45, 0x33, 0x18, 0xbd, 0x5e, 0xcf, 0xea, 0x5f, 0x86, 0x32, 0x8c, 0x6d, 0x8e, @@ -751,7 +751,7 @@ var txTests = []txTest{ Index: 1, }, SignatureScript: []byte{ - btcscript.OP_DATA_71, + txscript.OP_DATA_71, 0x30, 0x44, 0x02, 0x20, 0xc3, 0x02, 0x3b, 0xed, 0x85, 0x0d, 0x94, 0x27, 0x8e, 0x06, 0xd2, @@ -767,7 +767,7 @@ var txTests = []txTest{ 0x4a, 0x72, 0x73, 0xeb, 0x5b, 0x8d, 0x1d, 0xd7, 0x02, 0xcc, 0x01, - btcscript.OP_DATA_65, + txscript.OP_DATA_65, 0x04, 0x49, 0x5c, 0x8f, 0x66, 0x90, 0x0d, 0xb7, 0x62, 0x69, 0x0b, 0x54, 0x49, 0xa1, 0xf4, @@ -789,43 +789,43 @@ var txTests = []txTest{ { Value: 630320000, PkScript: []byte{ - btcscript.OP_DUP, - btcscript.OP_HASH160, - btcscript.OP_DATA_20, + txscript.OP_DUP, + txscript.OP_HASH160, + txscript.OP_DATA_20, 0x43, 0xdc, 0x32, 0x1b, 0x66, 0x00, 0x51, 0x1f, 0xe0, 0xa9, 0x6a, 0x97, 0xc2, 0x59, 0x3a, 0x90, 0x54, 0x29, 0x74, 0xd6, - btcscript.OP_EQUALVERIFY, - btcscript.OP_CHECKSIG, + txscript.OP_EQUALVERIFY, + txscript.OP_CHECKSIG, }, }, { Value: 100000181, PkScript: []byte{ - btcscript.OP_DUP, - btcscript.OP_HASH160, - btcscript.OP_DATA_20, + txscript.OP_DUP, + txscript.OP_HASH160, + txscript.OP_DATA_20, 0xa4, 0x05, 0xea, 0x18, 0x09, 0x14, 0xa9, 0x11, 0xd0, 0xb8, 0x07, 0x99, 0x19, 0x2b, 0x0b, 0x84, 0xae, 0x80, 0x1e, 0xbd, - btcscript.OP_EQUALVERIFY, - btcscript.OP_CHECKSIG, + txscript.OP_EQUALVERIFY, + txscript.OP_CHECKSIG, }, }, { Value: 596516343, PkScript: []byte{ - btcscript.OP_DUP, - btcscript.OP_HASH160, - btcscript.OP_DATA_20, + txscript.OP_DUP, + txscript.OP_HASH160, + txscript.OP_DATA_20, 0x24, 0x56, 0x76, 0x45, 0x4f, 0x6f, 0xff, 0x28, 0x88, 0x39, 0x47, 0xea, 0x70, 0x23, 0x86, 0x9b, 0x8a, 0x71, 0xa3, 0x05, - btcscript.OP_EQUALVERIFY, - btcscript.OP_CHECKSIG, + txscript.OP_EQUALVERIFY, + txscript.OP_CHECKSIG, }, }, }, @@ -833,22 +833,22 @@ var txTests = []txTest{ }, // Test input 0 pkScript: []byte{ - btcscript.OP_DUP, - btcscript.OP_HASH160, - btcscript.OP_DATA_20, + txscript.OP_DUP, + txscript.OP_HASH160, + txscript.OP_DATA_20, 0xfd, 0xf6, 0xea, 0xe7, 0x10, 0xa0, 0xc4, 0x49, 0x7a, 0x8d, 0x0f, 0xd2, 0x9a, 0xf6, 0x6b, 0xac, 0x94, 0xaf, 0x6c, 0x98, - btcscript.OP_EQUALVERIFY, - btcscript.OP_CHECKSIG, + txscript.OP_EQUALVERIFY, + txscript.OP_CHECKSIG, }, idx: 0, canonicalSigs: true, shouldFail: true, nSigOps: 1, - scriptInfo: btcscript.ScriptInfo{ - PkScriptClass: btcscript.PubKeyHashTy, + scriptInfo: txscript.ScriptInfo{ + PkScriptClass: txscript.PubKeyHashTy, NumInputs: 2, ExpectedInputs: 2, SigOps: 1, @@ -877,7 +877,7 @@ var txTests = []txTest{ Index: 1, }, SignatureScript: []byte{ - btcscript.OP_DATA_72, + txscript.OP_DATA_72, 0x30, 0x45, 0x02, 0x20, 0x58, 0x53, 0xc7, 0xf1, 0x39, 0x57, 0x85, 0xbf, 0xab, 0xb0, 0x3c, @@ -893,7 +893,7 @@ var txTests = []txTest{ 0x7d, 0x48, 0x5d, 0xc5, 0x29, 0xaf, 0xc5, 0x16, 0xc2, 0xdd, 0xb4, 0x81, - btcscript.OP_DATA_33, + txscript.OP_DATA_33, 0x03, 0x05, 0x58, 0x49, 0x80, 0x36, 0x7b, 0x32, 0x1f, 0xad, 0x7f, 0x1c, 0x1f, 0x4d, 0x5d, @@ -919,7 +919,7 @@ var txTests = []txTest{ Index: 1, }, SignatureScript: []byte{ - btcscript.OP_DATA_73, + txscript.OP_DATA_73, 0x30, 0x46, 0x02, 0x21, 0x00, 0x82, 0x69, 0xc9, 0xd7, 0xba, 0x0a, 0x7e, 0x73, 0x0d, 0xd1, @@ -935,7 +935,7 @@ var txTests = []txTest{ 0xbc, 0xff, 0x0d, 0x81, 0xd0, 0x5b, 0x39, 0xff, 0x0f, 0x42, 0x17, 0xb2, 0x81, - btcscript.OP_DATA_33, + txscript.OP_DATA_33, 0x03, 0xaa, 0xe3, 0x03, 0xd8, 0x25, 0x42, 0x15, 0x45, 0xc5, 0xbc, 0x7c, 0xcd, 0x5a, 0xc8, @@ -951,35 +951,35 @@ var txTests = []txTest{ { Value: 300000, PkScript: []byte{ - btcscript.OP_DUP, - btcscript.OP_HASH160, - btcscript.OP_DATA_20, + txscript.OP_DUP, + txscript.OP_HASH160, + txscript.OP_DATA_20, 0x5c, 0x11, 0xf9, 0x17, 0x88, 0x3b, 0x92, 0x7e, 0xef, 0x77, 0xdc, 0x57, 0x70, 0x7a, 0xeb, 0x85, 0x3f, 0x6d, 0x38, 0x94, - btcscript.OP_EQUALVERIFY, - btcscript.OP_CHECKSIG, + txscript.OP_EQUALVERIFY, + txscript.OP_CHECKSIG, }, }, }, LockTime: 0, }, pkScript: []byte{ - btcscript.OP_DUP, - btcscript.OP_HASH160, - btcscript.OP_DATA_20, + txscript.OP_DUP, + txscript.OP_HASH160, + txscript.OP_DATA_20, 0x85, 0x51, 0xe4, 0x8a, 0x53, 0xde, 0xcd, 0x1c, 0xfc, 0x63, 0x07, 0x9a, 0x45, 0x81, 0xbc, 0xcc, 0xfa, 0xd1, 0xa9, 0x3c, - btcscript.OP_EQUALVERIFY, - btcscript.OP_CHECKSIG, + txscript.OP_EQUALVERIFY, + txscript.OP_CHECKSIG, }, idx: 0, bip16: true, // after threshold nSigOps: 1, - scriptInfo: btcscript.ScriptInfo{ - PkScriptClass: btcscript.PubKeyHashTy, + scriptInfo: txscript.ScriptInfo{ + PkScriptClass: txscript.PubKeyHashTy, NumInputs: 2, ExpectedInputs: 2, SigOps: 1, @@ -1007,7 +1007,7 @@ var txTests = []txTest{ Index: 0, }, SignatureScript: []byte{ - btcscript.OP_DATA_71, + txscript.OP_DATA_71, 0x30, 0x44, 0x02, 0x20, 0x02, 0xdb, 0xe4, 0xb5, 0xa2, 0xfb, 0xb5, 0x21, 0xe4, 0xdc, 0x5f, @@ -1045,8 +1045,8 @@ var txTests = []txTest{ Index: 1, }, SignatureScript: []uint8{ - btcscript.OP_FALSE, - btcscript.OP_DATA_72, + txscript.OP_FALSE, + txscript.OP_DATA_72, 0x30, 0x45, 0x02, 0x20, 0x10, 0x6a, 0x3e, 0x4e, 0xf0, 0xb5, 0x1b, 0x76, 0x4a, 0x28, 0x87, @@ -1062,9 +1062,9 @@ var txTests = []txTest{ 0x1f, 0xe0, 0x72, 0x82, 0xe3, 0xb6, 0xec, 0xb5, 0xf3, 0xbb, 0x28, 0x01, - btcscript.OP_CODESEPARATOR, - btcscript.OP_TRUE, - btcscript.OP_DATA_33, + txscript.OP_CODESEPARATOR, + txscript.OP_TRUE, + txscript.OP_DATA_33, 0x02, 0x32, 0xab, 0xdc, 0x89, 0x3e, 0x7f, 0x06, 0x31, 0x36, 0x4d, 0x7f, 0xd0, 0x1c, 0xb3, @@ -1072,8 +1072,8 @@ var txTests = []txTest{ 0x9a, 0x00, 0x35, 0x7b, 0x3a, 0x78, 0x86, 0x21, 0x1a, 0xb4, 0x14, 0xd5, 0x5a, - btcscript.OP_TRUE, - btcscript.OP_CHECKMULTISIG, + txscript.OP_TRUE, + txscript.OP_CHECKMULTISIG, }, Sequence: 4294967295, }, @@ -1082,15 +1082,15 @@ var txTests = []txTest{ { Value: 4800000, PkScript: []byte{ - btcscript.OP_DUP, - btcscript.OP_HASH160, - btcscript.OP_DATA_20, + txscript.OP_DUP, + txscript.OP_HASH160, + txscript.OP_DATA_20, 0x0d, 0x77, 0x13, 0x64, 0x9f, 0x9a, 0x06, 0x78, 0xf4, 0xe8, 0x80, 0xb4, 0x0f, 0x86, 0xb9, 0x32, 0x89, 0xd1, 0xbb, 0x27, - btcscript.OP_EQUALVERIFY, - btcscript.OP_CHECKSIG, + txscript.OP_EQUALVERIFY, + txscript.OP_CHECKSIG, }, }, }, @@ -1098,16 +1098,16 @@ var txTests = []txTest{ }, // This is a very weird script... pkScript: []byte{ - btcscript.OP_DATA_20, + txscript.OP_DATA_20, 0x2a, 0x9b, 0xc5, 0x44, 0x7d, 0x66, 0x4c, 0x1d, 0x01, 0x41, 0x39, 0x2a, 0x84, 0x2d, 0x23, 0xdb, 0xa4, 0x5c, 0x4f, 0x13, - btcscript.OP_NOP2, btcscript.OP_DROP, + txscript.OP_NOP2, txscript.OP_DROP, }, idx: 1, bip16: false, nSigOps: 0, // multisig is in the pkScript! - scriptInfoErr: btcscript.ErrStackNonPushOnly, + scriptInfoErr: txscript.ErrStackNonPushOnly, }, // same as previous but with one byte changed to make signature fail { @@ -1130,7 +1130,7 @@ var txTests = []txTest{ Index: 0, }, SignatureScript: []byte{ - btcscript.OP_DATA_71, + txscript.OP_DATA_71, 0x30, 0x44, 0x02, 0x20, 0x02, 0xdb, 0xe4, 0xb5, 0xa2, 0xfb, 0xb5, 0x21, 0xe4, 0xdc, 0x5f, @@ -1168,8 +1168,8 @@ var txTests = []txTest{ Index: 1, }, SignatureScript: []uint8{ - btcscript.OP_FALSE, - btcscript.OP_DATA_72, + txscript.OP_FALSE, + txscript.OP_DATA_72, 0x30, 0x45, 0x02, 0x20, 0x10, 0x6a, 0x3e, 0x4e, 0xf0, 0xb5, 0x1b, 0x76, 0x4a, 0x28, 0x87, @@ -1185,9 +1185,9 @@ var txTests = []txTest{ 0x1f, 0xe0, 0x72, 0x82, 0xe3, 0xb6, 0xec, 0xb5, 0xf3, 0xbb, 0x28, 0x01, - btcscript.OP_CODESEPARATOR, - btcscript.OP_TRUE, - btcscript.OP_DATA_33, + txscript.OP_CODESEPARATOR, + txscript.OP_TRUE, + txscript.OP_DATA_33, 0x02, 0x32, 0xab, 0xdc, 0x89, 0x3e, 0x7f, 0x06, 0x31, 0x36, 0x4d, 0x7f, 0xd0, 0x1c, 0xb3, @@ -1195,8 +1195,8 @@ var txTests = []txTest{ 0x9a, 0x00, 0x35, 0x7b, 0x3a, 0x78, 0x86, 0x21, 0x1a, 0xb4, 0x14, 0xd5, 0x5a, - btcscript.OP_TRUE, - btcscript.OP_CHECKMULTISIG, + txscript.OP_TRUE, + txscript.OP_CHECKMULTISIG, }, Sequence: 4294967295, }, @@ -1205,15 +1205,15 @@ var txTests = []txTest{ { Value: 5800000, PkScript: []byte{ - btcscript.OP_DUP, - btcscript.OP_HASH160, - btcscript.OP_DATA_20, + txscript.OP_DUP, + txscript.OP_HASH160, + txscript.OP_DATA_20, 0x0d, 0x77, 0x13, 0x64, 0x9f, 0x9a, 0x06, 0x78, 0xf4, 0xe8, 0x80, 0xb4, 0x0f, 0x86, 0xb9, 0x32, 0x89, 0xd1, 0xbb, 0x27, - btcscript.OP_EQUALVERIFY, - btcscript.OP_CHECKSIG, + txscript.OP_EQUALVERIFY, + txscript.OP_CHECKSIG, }, }, }, @@ -1221,17 +1221,17 @@ var txTests = []txTest{ }, // This is a very weird script... pkScript: []byte{ - btcscript.OP_DATA_20, + txscript.OP_DATA_20, 0x2a, 0x9b, 0xc5, 0x44, 0x7d, 0x66, 0x4c, 0x1d, 0x01, 0x41, 0x39, 0x2a, 0x84, 0x2d, 0x23, 0xdb, 0xa4, 0x5c, 0x4f, 0x13, - btcscript.OP_NOP2, btcscript.OP_DROP, + txscript.OP_NOP2, txscript.OP_DROP, }, idx: 1, bip16: false, - err: btcscript.ErrStackScriptFailed, + err: txscript.ErrStackScriptFailed, nSigOps: 0, // multisig is in the pkScript! - scriptInfoErr: btcscript.ErrStackNonPushOnly, + scriptInfoErr: txscript.ErrStackNonPushOnly, }, // taken from tx b2d93dfd0b2c1a380e55e76a8d9cb3075dec9f4474e9485be008c337fd62c1f7 // on testnet @@ -1256,10 +1256,10 @@ var txTests = []txTest{ Index: 0, }, SignatureScript: []byte{ - btcscript.OP_0, - btcscript.OP_DATA_37, - btcscript.OP_0, - btcscript.OP_DATA_33, + txscript.OP_0, + txscript.OP_DATA_37, + txscript.OP_0, + txscript.OP_DATA_33, 0x02, 0x4a, 0xb3, 0x3c, 0x3a, 0x54, 0x7a, 0x37, 0x29, 0x3e, 0xb8, 0x75, 0xb4, 0xbb, 0xdb, @@ -1267,8 +1267,8 @@ var txTests = []txTest{ 0xfd, 0xf3, 0x56, 0x87, 0xe7, 0x97, 0x44, 0xdc, 0xd7, 0x0f, 0x6e, 0x4d, 0xe2, - btcscript.OP_1, - btcscript.OP_CHECKMULTISIG, + txscript.OP_1, + txscript.OP_CHECKMULTISIG, }, Sequence: 4294967295, }, @@ -1277,18 +1277,18 @@ var txTests = []txTest{ LockTime: 0, }, pkScript: []byte{ - btcscript.OP_HASH160, - btcscript.OP_DATA_20, + txscript.OP_HASH160, + txscript.OP_DATA_20, 0x2c, 0x6b, 0x10, 0x7f, 0xdf, 0x10, 0x6f, 0x22, 0x6f, 0x3f, 0xa3, 0x27, 0xba, 0x36, 0xd6, 0xe3, 0xca, 0xc7, 0x3d, 0xf0, - btcscript.OP_EQUAL, + txscript.OP_EQUAL, }, idx: 0, bip16: true, nSigOps: 1, - scriptInfo: btcscript.ScriptInfo{ - PkScriptClass: btcscript.ScriptHashTy, + scriptInfo: txscript.ScriptInfo{ + PkScriptClass: txscript.ScriptHashTy, NumInputs: 2, ExpectedInputs: 2, SigOps: 1, @@ -1316,7 +1316,7 @@ var txTests = []txTest{ Index: 0, }, SignatureScript: []byte{ - btcscript.OP_DATA_2, + txscript.OP_DATA_2, // OP_3 OP_7 0x53, 0x57, }, @@ -1327,33 +1327,33 @@ var txTests = []txTest{ { Value: 1000000, PkScript: []byte{ - btcscript.OP_DUP, - btcscript.OP_HASH160, - btcscript.OP_DATA_20, + txscript.OP_DUP, + txscript.OP_HASH160, + txscript.OP_DATA_20, 0x5b, 0x69, 0xd8, 0xb9, 0xdf, 0xa6, 0xe4, 0x12, 0x26, 0x47, 0xe1, 0x79, 0x4e, 0xaa, 0x3b, 0xfc, 0x11, 0x1f, 0x70, 0xef, - btcscript.OP_EQUALVERIFY, - btcscript.OP_CHECKSIG, + txscript.OP_EQUALVERIFY, + txscript.OP_CHECKSIG, }, }, }, LockTime: 0, }, pkScript: []byte{ - btcscript.OP_HASH160, - btcscript.OP_DATA_20, + txscript.OP_HASH160, + txscript.OP_DATA_20, 0x43, 0x3e, 0xc2, 0xac, 0x1f, 0xfa, 0x1b, 0x7b, 0x7d, 0x02, 0x7f, 0x56, 0x45, 0x29, 0xc5, 0x71, 0x97, 0xf9, 0xae, 0x88, - btcscript.OP_EQUAL, + txscript.OP_EQUAL, }, idx: 0, bip16: true, nSigOps: 0, // no signature ops in the pushed script. - scriptInfo: btcscript.ScriptInfo{ - PkScriptClass: btcscript.ScriptHashTy, + scriptInfo: txscript.ScriptInfo{ + PkScriptClass: txscript.ScriptHashTy, NumInputs: 1, ExpectedInputs: -1, // p2sh script is non standard SigOps: 0, @@ -1382,7 +1382,7 @@ var txTests = []txTest{ Index: 0, }, SignatureScript: []byte{ - btcscript.OP_DATA_2, + txscript.OP_DATA_2, // OP_3 OP_8 0x53, 0x58, }, @@ -1393,34 +1393,34 @@ var txTests = []txTest{ { Value: 1000000, PkScript: []byte{ - btcscript.OP_DUP, - btcscript.OP_HASH160, - btcscript.OP_DATA_20, + txscript.OP_DUP, + txscript.OP_HASH160, + txscript.OP_DATA_20, 0x5b, 0x69, 0xd8, 0xb9, 0xdf, 0xa6, 0xe4, 0x12, 0x26, 0x47, 0xe1, 0x79, 0x4e, 0xaa, 0x3b, 0xfc, 0x11, 0x1f, 0x70, 0xef, - btcscript.OP_EQUALVERIFY, - btcscript.OP_CHECKSIG, + txscript.OP_EQUALVERIFY, + txscript.OP_CHECKSIG, }, }, }, LockTime: 0, }, pkScript: []byte{ - btcscript.OP_HASH160, - btcscript.OP_DATA_20, + txscript.OP_HASH160, + txscript.OP_DATA_20, 0x43, 0x3e, 0xc2, 0xac, 0x1f, 0xfa, 0x1b, 0x7b, 0x7d, 0x02, 0x7f, 0x56, 0x45, 0x29, 0xc5, 0x71, 0x97, 0xf9, 0xae, 0x88, - btcscript.OP_EQUAL, + txscript.OP_EQUAL, }, idx: 0, - err: btcscript.ErrStackScriptFailed, + err: txscript.ErrStackScriptFailed, bip16: true, nSigOps: 0, // no signature ops in the pushed script. - scriptInfo: btcscript.ScriptInfo{ - PkScriptClass: btcscript.ScriptHashTy, + scriptInfo: txscript.ScriptInfo{ + PkScriptClass: txscript.ScriptHashTy, NumInputs: 1, ExpectedInputs: -1, // p2sh script is non standard SigOps: 0, @@ -1447,9 +1447,9 @@ var txTests = []txTest{ Index: 0, }, SignatureScript: []byte{ - btcscript.OP_DATA_2, + txscript.OP_DATA_2, // pushed script. - btcscript.OP_DATA_2, 0x1, + txscript.OP_DATA_2, 0x1, }, Sequence: 4294967295, }, @@ -1458,32 +1458,32 @@ var txTests = []txTest{ { Value: 1000000, PkScript: []byte{ - btcscript.OP_DUP, - btcscript.OP_HASH160, - btcscript.OP_DATA_20, + txscript.OP_DUP, + txscript.OP_HASH160, + txscript.OP_DATA_20, 0x5b, 0x69, 0xd8, 0xb9, 0xdf, 0xa6, 0xe4, 0x12, 0x26, 0x47, 0xe1, 0x79, 0x4e, 0xaa, 0x3b, 0xfc, 0x11, 0x1f, 0x70, 0xef, - btcscript.OP_EQUALVERIFY, - btcscript.OP_CHECKSIG, + txscript.OP_EQUALVERIFY, + txscript.OP_CHECKSIG, }, }, }, LockTime: 0, }, pkScript: []byte{ - btcscript.OP_HASH160, - btcscript.OP_DATA_20, + txscript.OP_HASH160, + txscript.OP_DATA_20, 0xd4, 0x8c, 0xe8, 0x6c, 0x69, 0x8f, 0x24, 0x68, 0x29, 0x92, 0x1b, 0xa9, 0xfb, 0x2a, 0x84, 0x4a, 0xe2, 0xad, 0xba, 0x67, - btcscript.OP_EQUAL, + txscript.OP_EQUAL, }, idx: 0, - err: btcscript.ErrStackShortScript, + err: txscript.ErrStackShortScript, bip16: true, - scriptInfoErr: btcscript.ErrStackShortScript, + scriptInfoErr: txscript.ErrStackShortScript, }, { // sigscript changed so to be non pushonly. @@ -1509,10 +1509,10 @@ var txTests = []txTest{ // will never run. SignatureScript: []byte{ - btcscript.OP_DATA_2, + txscript.OP_DATA_2, // pushed script. - btcscript.OP_DATA_1, 0x1, - btcscript.OP_DUP, + txscript.OP_DATA_1, 0x1, + txscript.OP_DUP, }, Sequence: 4294967295, }, @@ -1521,33 +1521,33 @@ var txTests = []txTest{ { Value: 1000000, PkScript: []byte{ - btcscript.OP_DUP, - btcscript.OP_HASH160, - btcscript.OP_DATA_20, + txscript.OP_DUP, + txscript.OP_HASH160, + txscript.OP_DATA_20, 0x5b, 0x69, 0xd8, 0xb9, 0xdf, 0xa6, 0xe4, 0x12, 0x26, 0x47, 0xe1, 0x79, 0x4e, 0xaa, 0x3b, 0xfc, 0x11, 0x1f, 0x70, 0xef, - btcscript.OP_EQUALVERIFY, - btcscript.OP_CHECKSIG, + txscript.OP_EQUALVERIFY, + txscript.OP_CHECKSIG, }, }, }, LockTime: 0, }, pkScript: []byte{ - btcscript.OP_HASH160, - btcscript.OP_DATA_20, + txscript.OP_HASH160, + txscript.OP_DATA_20, 0x43, 0x3e, 0xc2, 0xac, 0x1f, 0xfa, 0x1b, 0x7b, 0x7d, 0x02, 0x7f, 0x56, 0x45, 0x29, 0xc5, 0x71, 0x97, 0xf9, 0xae, 0x88, - btcscript.OP_EQUAL, + txscript.OP_EQUAL, }, idx: 0, - parseErr: btcscript.ErrStackP2SHNonPushOnly, + parseErr: txscript.ErrStackP2SHNonPushOnly, bip16: true, nSigOps: 0, // no signature ops in the pushed script. - scriptInfoErr: btcscript.ErrStackNonPushOnly, + scriptInfoErr: txscript.ErrStackNonPushOnly, }, { // sigscript changed so to be non pushonly. @@ -1572,7 +1572,7 @@ var txTests = []txTest{ // doesn't have to match signature. // will never run. SignatureScript: []byte{ - btcscript.OP_TRUE, + txscript.OP_TRUE, }, Sequence: 4294967295, }, @@ -1581,15 +1581,15 @@ var txTests = []txTest{ { Value: 1000000, PkScript: []byte{ - btcscript.OP_DUP, - btcscript.OP_HASH160, - btcscript.OP_DATA_20, + txscript.OP_DUP, + txscript.OP_HASH160, + txscript.OP_DATA_20, 0x5b, 0x69, 0xd8, 0xb9, 0xdf, 0xa6, 0xe4, 0x12, 0x26, 0x47, 0xe1, 0x79, 0x4e, 0xaa, 0x3b, 0xfc, 0x11, 0x1f, 0x70, 0xef, - btcscript.OP_EQUALVERIFY, - btcscript.OP_CHECKSIG, + txscript.OP_EQUALVERIFY, + txscript.OP_CHECKSIG, }, }, }, @@ -1599,8 +1599,8 @@ var txTests = []txTest{ idx: 0, bip16: true, nSigOps: 0, // no signature ops in the pushed script. - scriptInfo: btcscript.ScriptInfo{ - PkScriptClass: btcscript.NonStandardTy, + scriptInfo: txscript.ScriptInfo{ + PkScriptClass: txscript.NonStandardTy, NumInputs: 1, ExpectedInputs: -1, SigOps: 0, @@ -1615,14 +1615,14 @@ var txTests = []txTest{ // nothing in the blockchain that we have yet seen uses them, making it hard // to confirm we implemented the spec correctly. func testTx(t *testing.T, test txTest) { - var flags btcscript.ScriptFlags + var flags txscript.ScriptFlags if test.bip16 { - flags |= btcscript.ScriptBip16 + flags |= txscript.ScriptBip16 } if test.canonicalSigs { - flags |= btcscript.ScriptCanonicalSignatures + flags |= txscript.ScriptCanonicalSignatures } - engine, err := btcscript.NewScript( + engine, err := txscript.NewScript( test.tx.TxIn[test.idx].SignatureScript, test.pkScript, test.idx, test.tx, flags) if err != nil { @@ -1669,7 +1669,7 @@ func TestGetPreciseSignOps(t *testing.T) { // First we go over the range of tests in testTx and count the sigops in // them. for _, test := range txTests { - count := btcscript.GetPreciseSigOpCount( + count := txscript.GetPreciseSigOpCount( test.tx.TxIn[test.idx].SignatureScript, test.pkScript, test.bip16) if count != test.nSigOps { @@ -1691,12 +1691,12 @@ func TestGetPreciseSignOps(t *testing.T) { psocTests := []psocTest{ { name: "scriptSig doesn't parse", - scriptSig: []byte{btcscript.OP_PUSHDATA1, 2}, - err: btcscript.ErrStackShortScript, + scriptSig: []byte{txscript.OP_PUSHDATA1, 2}, + err: txscript.ErrStackShortScript, }, { name: "scriptSig isn't push only", - scriptSig: []byte{btcscript.OP_1, btcscript.OP_DUP}, + scriptSig: []byte{txscript.OP_1, txscript.OP_DUP}, nSigOps: 0, }, { @@ -1707,30 +1707,30 @@ func TestGetPreciseSignOps(t *testing.T) { { name: "No script at the end", // No script at end but still push only. - scriptSig: []byte{btcscript.OP_1, btcscript.OP_1}, + scriptSig: []byte{txscript.OP_1, txscript.OP_1}, nSigOps: 0, }, // pushed script doesn't parse. { name: "pushed script doesn't parse", - scriptSig: []byte{btcscript.OP_DATA_2, - btcscript.OP_PUSHDATA1, 2}, - err: btcscript.ErrStackShortScript, + scriptSig: []byte{txscript.OP_DATA_2, + txscript.OP_PUSHDATA1, 2}, + err: txscript.ErrStackShortScript, }, } // The signature in the p2sh script is nonsensical for the tests since // this script will never be executed. What matters is that it matches // the right pattern. pkScript := []byte{ - btcscript.OP_HASH160, - btcscript.OP_DATA_20, + txscript.OP_HASH160, + txscript.OP_DATA_20, 0x43, 0x3e, 0xc2, 0xac, 0x1f, 0xfa, 0x1b, 0x7b, 0x7d, 0x02, 0x7f, 0x56, 0x45, 0x29, 0xc5, 0x71, 0x97, 0xf9, 0xae, 0x88, - btcscript.OP_EQUAL, + txscript.OP_EQUAL, } for _, test := range psocTests { - count := btcscript.GetPreciseSigOpCount( + count := txscript.GetPreciseSigOpCount( test.scriptSig, pkScript, true) if count != test.nSigOps { t.Errorf("%s: expected count of %d, got %d", test.name, @@ -1745,7 +1745,7 @@ type scriptInfoTest struct { sigScript []byte pkScript []byte bip16 bool - scriptInfo btcscript.ScriptInfo + scriptInfo txscript.ScriptInfo scriptInfoErr error } @@ -1753,7 +1753,7 @@ func TestScriptInfo(t *testing.T) { t.Parallel() for _, test := range txTests { - si, err := btcscript.CalcScriptInfo( + si, err := txscript.CalcScriptInfo( test.tx.TxIn[test.idx].SignatureScript, test.pkScript, test.bip16) if err != nil { @@ -1781,65 +1781,65 @@ func TestScriptInfo(t *testing.T) { { // Invented scripts, the hashes do not match name: "pkscript doesn't parse", - sigScript: []byte{btcscript.OP_TRUE, - btcscript.OP_DATA_1, 81, - btcscript.OP_DATA_8, - btcscript.OP_2DUP, btcscript.OP_EQUAL, - btcscript.OP_NOT, btcscript.OP_VERIFY, - btcscript.OP_ABS, btcscript.OP_SWAP, - btcscript.OP_ABS, btcscript.OP_EQUAL, + sigScript: []byte{txscript.OP_TRUE, + txscript.OP_DATA_1, 81, + txscript.OP_DATA_8, + txscript.OP_2DUP, txscript.OP_EQUAL, + txscript.OP_NOT, txscript.OP_VERIFY, + txscript.OP_ABS, txscript.OP_SWAP, + txscript.OP_ABS, txscript.OP_EQUAL, }, // truncated version of test below: - pkScript: []byte{btcscript.OP_HASH160, - btcscript.OP_DATA_20, + pkScript: []byte{txscript.OP_HASH160, + txscript.OP_DATA_20, 0xfe, 0x44, 0x10, 0x65, 0xb6, 0x53, 0x22, 0x31, 0xde, 0x2f, 0xac, 0x56, 0x31, 0x52, 0x20, 0x5e, 0xc4, 0xf5, 0x9c, }, bip16: true, - scriptInfoErr: btcscript.ErrStackShortScript, + scriptInfoErr: txscript.ErrStackShortScript, }, { name: "sigScript doesn't parse", // Truncated version of p2sh script below. - sigScript: []byte{btcscript.OP_TRUE, - btcscript.OP_DATA_1, 81, - btcscript.OP_DATA_8, - btcscript.OP_2DUP, btcscript.OP_EQUAL, - btcscript.OP_NOT, btcscript.OP_VERIFY, - btcscript.OP_ABS, btcscript.OP_SWAP, - btcscript.OP_ABS, + sigScript: []byte{txscript.OP_TRUE, + txscript.OP_DATA_1, 81, + txscript.OP_DATA_8, + txscript.OP_2DUP, txscript.OP_EQUAL, + txscript.OP_NOT, txscript.OP_VERIFY, + txscript.OP_ABS, txscript.OP_SWAP, + txscript.OP_ABS, }, - pkScript: []byte{btcscript.OP_HASH160, - btcscript.OP_DATA_20, + pkScript: []byte{txscript.OP_HASH160, + txscript.OP_DATA_20, 0xfe, 0x44, 0x10, 0x65, 0xb6, 0x53, 0x22, 0x31, 0xde, 0x2f, 0xac, 0x56, 0x31, 0x52, 0x20, 0x5e, - 0xc4, 0xf5, 0x9c, 0x74, btcscript.OP_EQUAL, + 0xc4, 0xf5, 0x9c, 0x74, txscript.OP_EQUAL, }, bip16: true, - scriptInfoErr: btcscript.ErrStackShortScript, + scriptInfoErr: txscript.ErrStackShortScript, }, { // Invented scripts, the hashes do not match name: "p2sh standard script", - sigScript: []byte{btcscript.OP_TRUE, - btcscript.OP_DATA_1, 81, - btcscript.OP_DATA_25, - btcscript.OP_DUP, btcscript.OP_HASH160, - btcscript.OP_DATA_20, 0x1, 0x2, 0x3, 0x4, 0x5, + sigScript: []byte{txscript.OP_TRUE, + txscript.OP_DATA_1, 81, + txscript.OP_DATA_25, + txscript.OP_DUP, txscript.OP_HASH160, + txscript.OP_DATA_20, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, - btcscript.OP_EQUALVERIFY, btcscript.OP_CHECKSIG, + txscript.OP_EQUALVERIFY, txscript.OP_CHECKSIG, }, - pkScript: []byte{btcscript.OP_HASH160, - btcscript.OP_DATA_20, + pkScript: []byte{txscript.OP_HASH160, + txscript.OP_DATA_20, 0xfe, 0x44, 0x10, 0x65, 0xb6, 0x53, 0x22, 0x31, 0xde, 0x2f, 0xac, 0x56, 0x31, 0x52, 0x20, 0x5e, - 0xc4, 0xf5, 0x9c, 0x74, btcscript.OP_EQUAL, + 0xc4, 0xf5, 0x9c, 0x74, txscript.OP_EQUAL, }, bip16: true, - scriptInfo: btcscript.ScriptInfo{ - PkScriptClass: btcscript.ScriptHashTy, + scriptInfo: txscript.ScriptInfo{ + PkScriptClass: txscript.ScriptHashTy, NumInputs: 3, ExpectedInputs: 3, // nonstandard p2sh. SigOps: 1, @@ -1849,23 +1849,23 @@ func TestScriptInfo(t *testing.T) { // from 567a53d1ce19ce3d07711885168484439965501536d0d0294c5d46d46c10e53b // from the blockchain. name: "p2sh nonstandard script", - sigScript: []byte{btcscript.OP_TRUE, - btcscript.OP_DATA_1, 81, - btcscript.OP_DATA_8, - btcscript.OP_2DUP, btcscript.OP_EQUAL, - btcscript.OP_NOT, btcscript.OP_VERIFY, - btcscript.OP_ABS, btcscript.OP_SWAP, - btcscript.OP_ABS, btcscript.OP_EQUAL, + sigScript: []byte{txscript.OP_TRUE, + txscript.OP_DATA_1, 81, + txscript.OP_DATA_8, + txscript.OP_2DUP, txscript.OP_EQUAL, + txscript.OP_NOT, txscript.OP_VERIFY, + txscript.OP_ABS, txscript.OP_SWAP, + txscript.OP_ABS, txscript.OP_EQUAL, }, - pkScript: []byte{btcscript.OP_HASH160, - btcscript.OP_DATA_20, + pkScript: []byte{txscript.OP_HASH160, + txscript.OP_DATA_20, 0xfe, 0x44, 0x10, 0x65, 0xb6, 0x53, 0x22, 0x31, 0xde, 0x2f, 0xac, 0x56, 0x31, 0x52, 0x20, 0x5e, - 0xc4, 0xf5, 0x9c, 0x74, btcscript.OP_EQUAL, + 0xc4, 0xf5, 0x9c, 0x74, txscript.OP_EQUAL, }, bip16: true, - scriptInfo: btcscript.ScriptInfo{ - PkScriptClass: btcscript.ScriptHashTy, + scriptInfo: txscript.ScriptInfo{ + PkScriptClass: txscript.ScriptHashTy, NumInputs: 3, ExpectedInputs: -1, // nonstandard p2sh. SigOps: 0, @@ -1874,31 +1874,31 @@ func TestScriptInfo(t *testing.T) { { // Script is invented, numbers all fake. name: "multisig script", - sigScript: []byte{btcscript.OP_TRUE, - btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_0, // Extra arg for OP_CHECKMULTISIG bug + sigScript: []byte{txscript.OP_TRUE, + txscript.OP_TRUE, txscript.OP_TRUE, + txscript.OP_0, // Extra arg for OP_CHECKMULTISIG bug }, pkScript: []byte{ - btcscript.OP_3, btcscript.OP_DATA_33, + txscript.OP_3, txscript.OP_DATA_33, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, - btcscript.OP_DATA_33, + txscript.OP_DATA_33, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, - btcscript.OP_DATA_33, + txscript.OP_DATA_33, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, - btcscript.OP_3, btcscript.OP_CHECKMULTISIG, + txscript.OP_3, txscript.OP_CHECKMULTISIG, }, bip16: true, - scriptInfo: btcscript.ScriptInfo{ - PkScriptClass: btcscript.MultiSigTy, + scriptInfo: txscript.ScriptInfo{ + PkScriptClass: txscript.MultiSigTy, NumInputs: 4, ExpectedInputs: 4, SigOps: 3, @@ -1907,7 +1907,7 @@ func TestScriptInfo(t *testing.T) { } for _, test := range extraTests { - si, err := btcscript.CalcScriptInfo(test.sigScript, + si, err := txscript.CalcScriptInfo(test.sigScript, test.pkScript, test.bip16) if err != nil { if err != test.scriptInfoErr { @@ -1944,50 +1944,50 @@ var removeOpcodeTests = []removeOpcodeTest{ // Nothing to remove. { name: "nothing to remove", - before: []byte{btcscript.OP_NOP}, - remove: btcscript.OP_CODESEPARATOR, - after: []byte{btcscript.OP_NOP}, + before: []byte{txscript.OP_NOP}, + remove: txscript.OP_CODESEPARATOR, + after: []byte{txscript.OP_NOP}, }, // Test basic opcode removal { name: "codeseparator 1", - before: []byte{btcscript.OP_NOP, btcscript.OP_CODESEPARATOR, - btcscript.OP_TRUE}, - remove: btcscript.OP_CODESEPARATOR, - after: []byte{btcscript.OP_NOP, btcscript.OP_TRUE}, + before: []byte{txscript.OP_NOP, txscript.OP_CODESEPARATOR, + txscript.OP_TRUE}, + remove: txscript.OP_CODESEPARATOR, + after: []byte{txscript.OP_NOP, txscript.OP_TRUE}, }, // The opcode in question is actually part of the data in a previous // opcode { name: "codeseparator by coincidence", - before: []byte{btcscript.OP_NOP, btcscript.OP_DATA_1, btcscript.OP_CODESEPARATOR, - btcscript.OP_TRUE}, - remove: btcscript.OP_CODESEPARATOR, - after: []byte{btcscript.OP_NOP, btcscript.OP_DATA_1, btcscript.OP_CODESEPARATOR, - btcscript.OP_TRUE}, + before: []byte{txscript.OP_NOP, txscript.OP_DATA_1, txscript.OP_CODESEPARATOR, + txscript.OP_TRUE}, + remove: txscript.OP_CODESEPARATOR, + after: []byte{txscript.OP_NOP, txscript.OP_DATA_1, txscript.OP_CODESEPARATOR, + txscript.OP_TRUE}, }, { name: "invalid opcode", - before: []byte{btcscript.OP_UNKNOWN186}, - remove: btcscript.OP_CODESEPARATOR, - after: []byte{btcscript.OP_UNKNOWN186}, + before: []byte{txscript.OP_UNKNOWN186}, + remove: txscript.OP_CODESEPARATOR, + after: []byte{txscript.OP_UNKNOWN186}, }, { name: "invalid length (insruction)", - before: []byte{btcscript.OP_PUSHDATA1}, - remove: btcscript.OP_CODESEPARATOR, - err: btcscript.ErrStackShortScript, + before: []byte{txscript.OP_PUSHDATA1}, + remove: txscript.OP_CODESEPARATOR, + err: txscript.ErrStackShortScript, }, { name: "invalid length (data)", - before: []byte{btcscript.OP_PUSHDATA1, 255, 254}, - remove: btcscript.OP_CODESEPARATOR, - err: btcscript.ErrStackShortScript, + before: []byte{txscript.OP_PUSHDATA1, 255, 254}, + remove: txscript.OP_CODESEPARATOR, + err: txscript.ErrStackShortScript, }, } func testRemoveOpcode(t *testing.T, test *removeOpcodeTest) { - result, err := btcscript.TstRemoveOpcode(test.before, test.remove) + result, err := txscript.TstRemoveOpcode(test.before, test.remove) if test.err != nil { if err != test.err { t.Errorf("%s: got unexpected error. exp: \"%v\" "+ @@ -2024,110 +2024,110 @@ type removeOpcodeByDataTest struct { var removeOpcodeByDataTests = []removeOpcodeByDataTest{ { name: "nothing to do", - before: []byte{btcscript.OP_NOP}, + before: []byte{txscript.OP_NOP}, remove: []byte{1, 2, 3, 4}, - after: []byte{btcscript.OP_NOP}, + after: []byte{txscript.OP_NOP}, }, { name: "simple case", - before: []byte{btcscript.OP_DATA_4, 1, 2, 3, 4}, + before: []byte{txscript.OP_DATA_4, 1, 2, 3, 4}, remove: []byte{1, 2, 3, 4}, after: []byte{}, }, { name: "simple case (miss)", - before: []byte{btcscript.OP_DATA_4, 1, 2, 3, 4}, + before: []byte{txscript.OP_DATA_4, 1, 2, 3, 4}, remove: []byte{1, 2, 3, 5}, - after: []byte{btcscript.OP_DATA_4, 1, 2, 3, 4}, + after: []byte{txscript.OP_DATA_4, 1, 2, 3, 4}, }, { // padded to keep it canonical. name: "simple case (pushdata1)", - before: append(append([]byte{btcscript.OP_PUSHDATA1, 76}, + before: append(append([]byte{txscript.OP_PUSHDATA1, 76}, bytes.Repeat([]byte{0}, 72)...), []byte{1, 2, 3, 4}...), remove: []byte{1, 2, 3, 4}, after: []byte{}, }, { name: "simple case (pushdata1 miss)", - before: append(append([]byte{btcscript.OP_PUSHDATA1, 76}, + before: append(append([]byte{txscript.OP_PUSHDATA1, 76}, bytes.Repeat([]byte{0}, 72)...), []byte{1, 2, 3, 4}...), remove: []byte{1, 2, 3, 5}, - after: append(append([]byte{btcscript.OP_PUSHDATA1, 76}, + after: append(append([]byte{txscript.OP_PUSHDATA1, 76}, bytes.Repeat([]byte{0}, 72)...), []byte{1, 2, 3, 4}...), }, { name: "simple case (pushdata1 miss noncanonical)", - before: []byte{btcscript.OP_PUSHDATA1, 4, 1, 2, 3, 4}, + before: []byte{txscript.OP_PUSHDATA1, 4, 1, 2, 3, 4}, remove: []byte{1, 2, 3, 4}, - after: []byte{btcscript.OP_PUSHDATA1, 4, 1, 2, 3, 4}, + after: []byte{txscript.OP_PUSHDATA1, 4, 1, 2, 3, 4}, }, { name: "simple case (pushdata2)", - before: append(append([]byte{btcscript.OP_PUSHDATA2, 0, 1}, + before: append(append([]byte{txscript.OP_PUSHDATA2, 0, 1}, bytes.Repeat([]byte{0}, 252)...), []byte{1, 2, 3, 4}...), remove: []byte{1, 2, 3, 4}, after: []byte{}, }, { name: "simple case (pushdata2 miss)", - before: append(append([]byte{btcscript.OP_PUSHDATA2, 0, 1}, + before: append(append([]byte{txscript.OP_PUSHDATA2, 0, 1}, bytes.Repeat([]byte{0}, 252)...), []byte{1, 2, 3, 4}...), remove: []byte{1, 2, 3, 4, 5}, - after: append(append([]byte{btcscript.OP_PUSHDATA2, 0, 1}, + after: append(append([]byte{txscript.OP_PUSHDATA2, 0, 1}, bytes.Repeat([]byte{0}, 252)...), []byte{1, 2, 3, 4}...), }, { name: "simple case (pushdata2 miss noncanonical)", - before: []byte{btcscript.OP_PUSHDATA2, 4, 0, 1, 2, 3, 4}, + before: []byte{txscript.OP_PUSHDATA2, 4, 0, 1, 2, 3, 4}, remove: []byte{1, 2, 3, 4}, - after: []byte{btcscript.OP_PUSHDATA2, 4, 0, 1, 2, 3, 4}, + after: []byte{txscript.OP_PUSHDATA2, 4, 0, 1, 2, 3, 4}, }, { // This is padded to make the push canonical. name: "simple case (pushdata4)", - before: append(append([]byte{btcscript.OP_PUSHDATA4, 0, 0, 1, 0}, + before: append(append([]byte{txscript.OP_PUSHDATA4, 0, 0, 1, 0}, bytes.Repeat([]byte{0}, 65532)...), []byte{1, 2, 3, 4}...), remove: []byte{1, 2, 3, 4}, after: []byte{}, }, { name: "simple case (pushdata4 miss noncanonical)", - before: []byte{btcscript.OP_PUSHDATA4, 4, 0, 0, 0, 1, 2, 3, 4}, + before: []byte{txscript.OP_PUSHDATA4, 4, 0, 0, 0, 1, 2, 3, 4}, remove: []byte{1, 2, 3, 4}, - after: []byte{btcscript.OP_PUSHDATA4, 4, 0, 0, 0, 1, 2, 3, 4}, + after: []byte{txscript.OP_PUSHDATA4, 4, 0, 0, 0, 1, 2, 3, 4}, }, { // This is padded to make the push canonical. name: "simple case (pushdata4 miss)", - before: append(append([]byte{btcscript.OP_PUSHDATA4, 0, 0, 1, 0}, + before: append(append([]byte{txscript.OP_PUSHDATA4, 0, 0, 1, 0}, bytes.Repeat([]byte{0}, 65532)...), []byte{1, 2, 3, 4}...), remove: []byte{1, 2, 3, 4, 5}, - after: append(append([]byte{btcscript.OP_PUSHDATA4, 0, 0, 1, 0}, + after: append(append([]byte{txscript.OP_PUSHDATA4, 0, 0, 1, 0}, bytes.Repeat([]byte{0}, 65532)...), []byte{1, 2, 3, 4}...), }, { name: "invalid opcode ", - before: []byte{btcscript.OP_UNKNOWN187}, + before: []byte{txscript.OP_UNKNOWN187}, remove: []byte{1, 2, 3, 4}, - after: []byte{btcscript.OP_UNKNOWN187}, + after: []byte{txscript.OP_UNKNOWN187}, }, { name: "invalid length (instruction)", - before: []byte{btcscript.OP_PUSHDATA1}, + before: []byte{txscript.OP_PUSHDATA1}, remove: []byte{1, 2, 3, 4}, - err: btcscript.ErrStackShortScript, + err: txscript.ErrStackShortScript, }, { name: "invalid length (data)", - before: []byte{btcscript.OP_PUSHDATA1, 255, 254}, + before: []byte{txscript.OP_PUSHDATA1, 255, 254}, remove: []byte{1, 2, 3, 4}, - err: btcscript.ErrStackShortScript, + err: txscript.ErrStackShortScript, }, } func testRemoveOpcodeByData(t *testing.T, test *removeOpcodeByDataTest) { - result, err := btcscript.TstRemoveOpcodeByData(test.before, + result, err := txscript.TstRemoveOpcodeByData(test.before, test.remove) if test.err != nil { if err != test.err { @@ -2158,7 +2158,7 @@ func TestRemoveOpcodeByDatas(t *testing.T) { type scriptTypeTest struct { name string script []byte - scripttype btcscript.ScriptClass + scripttype txscript.ScriptClass } var scriptTypeTests = []scriptTypeTest{ @@ -2166,7 +2166,7 @@ var scriptTypeTests = []scriptTypeTest{ { name: "Pay Pubkey", script: []byte{ - btcscript.OP_DATA_65, + txscript.OP_DATA_65, 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 0xd7, @@ -2175,24 +2175,24 @@ var scriptTypeTests = []scriptTypeTest{ 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, 0xa3, - btcscript.OP_CHECKSIG, + txscript.OP_CHECKSIG, }, - scripttype: btcscript.PubKeyTy, + scripttype: txscript.PubKeyTy, }, // tx 599e47a8114fe098103663029548811d2651991b62397e057f0c863c2bc9f9ea { name: "Pay PubkeyHash", script: []byte{ - btcscript.OP_DUP, - btcscript.OP_HASH160, - btcscript.OP_DATA_20, + txscript.OP_DUP, + txscript.OP_HASH160, + txscript.OP_DATA_20, 0x66, 0x0d, 0x4e, 0xf3, 0xa7, 0x43, 0xe3, 0xe6, 0x96, 0xad, 0x99, 0x03, 0x64, 0xe5, 0x55, 0xc2, 0x71, 0xad, 0x50, 0x4b, - btcscript.OP_EQUALVERIFY, - btcscript.OP_CHECKSIG, + txscript.OP_EQUALVERIFY, + txscript.OP_CHECKSIG, }, - scripttype: btcscript.PubKeyHashTy, + scripttype: txscript.PubKeyHashTy, }, // part of tx 6d36bc17e947ce00bb6f12f8e7a56a1585c5a36188ffa2b05e10b4743273a74b // codeseparator parts have been elided. (bitcoind's checks for multisig @@ -2200,55 +2200,55 @@ var scriptTypeTests = []scriptTypeTest{ { name: "multisig", script: []byte{ - btcscript.OP_TRUE, - btcscript.OP_DATA_33, + txscript.OP_TRUE, + txscript.OP_DATA_33, 0x02, 0x32, 0xab, 0xdc, 0x89, 0x3e, 0x7f, 0x06, 0x31, 0x36, 0x4d, 0x7f, 0xd0, 0x1c, 0xb3, 0x3d, 0x24, 0xda, 0x45, 0x32, 0x9a, 0x00, 0x35, 0x7b, 0x3a, 0x78, 0x86, 0x21, 0x1a, 0xb4, 0x14, 0xd5, 0x5a, - btcscript.OP_TRUE, - btcscript.OP_CHECKMULTISIG, + txscript.OP_TRUE, + txscript.OP_CHECKMULTISIG, }, - scripttype: btcscript.MultiSigTy, + scripttype: txscript.MultiSigTy, }, // tx e5779b9e78f9650debc2893fd9636d827b26b4ddfa6a8172fe8708c924f5c39d // P2SH { name: "P2SH", script: []byte{ - btcscript.OP_HASH160, - btcscript.OP_DATA_20, + txscript.OP_HASH160, + txscript.OP_DATA_20, 0x43, 0x3e, 0xc2, 0xac, 0x1f, 0xfa, 0x1b, 0x7b, 0x7d, 0x02, 0x7f, 0x56, 0x45, 0x29, 0xc5, 0x71, 0x97, 0xf9, 0xae, 0x88, - btcscript.OP_EQUAL, + txscript.OP_EQUAL, }, - scripttype: btcscript.ScriptHashTy, + scripttype: txscript.ScriptHashTy, }, // Nulldata with no data at all. { name: "nulldata", script: []byte{ - btcscript.OP_RETURN, + txscript.OP_RETURN, }, - scripttype: btcscript.NullDataTy, + scripttype: txscript.NullDataTy, }, // Nulldata with small data. { name: "nulldata2", script: []byte{ - btcscript.OP_RETURN, - btcscript.OP_DATA_8, + txscript.OP_RETURN, + txscript.OP_DATA_8, 0x04, 0x67, 0x08, 0xaf, 0xdb, 0x0f, 0xe5, 0x54, }, - scripttype: btcscript.NullDataTy, + scripttype: txscript.NullDataTy, }, // Nulldata with max allowed data. { name: "nulldata3", script: []byte{ - btcscript.OP_RETURN, - btcscript.OP_PUSHDATA1, + txscript.OP_RETURN, + txscript.OP_PUSHDATA1, 0x28, // 40 0x04, 0x67, 0x08, 0xaf, 0xdb, 0x0f, 0xe5, 0x54, 0x82, 0x71, 0x96, 0x7f, 0x1a, 0x67, 0x13, 0x0b, @@ -2256,14 +2256,14 @@ var scriptTypeTests = []scriptTypeTest{ 0x9a, 0x67, 0x96, 0x2e, 0x0e, 0xa1, 0xf6, 0x1d, 0xeb, 0x64, 0x9f, 0x6b, 0xc3, 0xf4, 0xce, 0xf3, }, - scripttype: btcscript.NullDataTy, + scripttype: txscript.NullDataTy, }, // Nulldata with more than max allowed data (so therefore nonstandard) { name: "nulldata4", script: []byte{ - btcscript.OP_RETURN, - btcscript.OP_PUSHDATA1, + txscript.OP_RETURN, + txscript.OP_PUSHDATA1, 0x29, // 41 0x04, 0x67, 0x08, 0xaf, 0xdb, 0x0f, 0xe5, 0x54, 0x82, 0x71, 0x96, 0x7f, 0x1a, 0x67, 0x13, 0x0b, @@ -2272,102 +2272,102 @@ var scriptTypeTests = []scriptTypeTest{ 0xeb, 0x64, 0x9f, 0x6b, 0xc3, 0xf4, 0xce, 0xf3, 0x08, }, - scripttype: btcscript.NonStandardTy, + scripttype: txscript.NonStandardTy, }, // Almost nulldata, but add an additional opcode after the data to make // it nonstandard. { name: "nulldata5", script: []byte{ - btcscript.OP_RETURN, - btcscript.OP_DATA_1, + txscript.OP_RETURN, + txscript.OP_DATA_1, 0x04, - btcscript.OP_TRUE, + txscript.OP_TRUE, }, - scripttype: btcscript.NonStandardTy, + scripttype: txscript.NonStandardTy, }, // The next few are almost multisig (it is the more complex script type) // but with various changes to make it fail. { // multisig but funny nsigs.. name: "strange 1", script: []byte{ - btcscript.OP_DUP, - btcscript.OP_DATA_33, + txscript.OP_DUP, + txscript.OP_DATA_33, 0x02, 0x32, 0xab, 0xdc, 0x89, 0x3e, 0x7f, 0x06, 0x31, 0x36, 0x4d, 0x7f, 0xd0, 0x1c, 0xb3, 0x3d, 0x24, 0xda, 0x45, 0x32, 0x9a, 0x00, 0x35, 0x7b, 0x3a, 0x78, 0x86, 0x21, 0x1a, 0xb4, 0x14, 0xd5, 0x5a, - btcscript.OP_TRUE, - btcscript.OP_CHECKMULTISIG, + txscript.OP_TRUE, + txscript.OP_CHECKMULTISIG, }, - scripttype: btcscript.NonStandardTy, + scripttype: txscript.NonStandardTy, }, { name: "strange 2", // multisig but funny pubkey. script: []byte{ - btcscript.OP_TRUE, - btcscript.OP_TRUE, - btcscript.OP_TRUE, - btcscript.OP_CHECKMULTISIG, + txscript.OP_TRUE, + txscript.OP_TRUE, + txscript.OP_TRUE, + txscript.OP_CHECKMULTISIG, }, - scripttype: btcscript.NonStandardTy, + scripttype: txscript.NonStandardTy, }, { name: "strange 3", // multisig but no matching npubkeys opcode. script: []byte{ - btcscript.OP_TRUE, - btcscript.OP_DATA_33, + txscript.OP_TRUE, + txscript.OP_DATA_33, 0x02, 0x32, 0xab, 0xdc, 0x89, 0x3e, 0x7f, 0x06, 0x31, 0x36, 0x4d, 0x7f, 0xd0, 0x1c, 0xb3, 0x3d, 0x24, 0xda, 0x45, 0x32, 0x9a, 0x00, 0x35, 0x7b, 0x3a, 0x78, 0x86, 0x21, 0x1a, 0xb4, 0x14, 0xd5, 0x5a, - btcscript.OP_DATA_33, + txscript.OP_DATA_33, 0x02, 0x32, 0xab, 0xdc, 0x89, 0x3e, 0x7f, 0x06, 0x31, 0x36, 0x4d, 0x7f, 0xd0, 0x1c, 0xb3, 0x3d, 0x24, 0xda, 0x45, 0x32, 0x9a, 0x00, 0x35, 0x7b, 0x3a, 0x78, 0x86, 0x21, 0x1a, 0xb4, 0x14, 0xd5, 0x5a, // No number. - btcscript.OP_CHECKMULTISIG, + txscript.OP_CHECKMULTISIG, }, - scripttype: btcscript.NonStandardTy, + scripttype: txscript.NonStandardTy, }, { name: "strange 4", // multisig but with multisigverify script: []byte{ - btcscript.OP_TRUE, - btcscript.OP_DATA_33, + txscript.OP_TRUE, + txscript.OP_DATA_33, 0x02, 0x32, 0xab, 0xdc, 0x89, 0x3e, 0x7f, 0x06, 0x31, 0x36, 0x4d, 0x7f, 0xd0, 0x1c, 0xb3, 0x3d, 0x24, 0xda, 0x45, 0x32, 0x9a, 0x00, 0x35, 0x7b, 0x3a, 0x78, 0x86, 0x21, 0x1a, 0xb4, 0x14, 0xd5, 0x5a, - btcscript.OP_TRUE, - btcscript.OP_CHECKMULTISIGVERIFY, + txscript.OP_TRUE, + txscript.OP_CHECKMULTISIGVERIFY, }, - scripttype: btcscript.NonStandardTy, + scripttype: txscript.NonStandardTy, }, { name: "strange 5", // multisig but wrong length. script: []byte{ - btcscript.OP_TRUE, - btcscript.OP_CHECKMULTISIG, + txscript.OP_TRUE, + txscript.OP_CHECKMULTISIG, }, - scripttype: btcscript.NonStandardTy, + scripttype: txscript.NonStandardTy, }, { name: "doesn't parse", script: []byte{ - btcscript.OP_DATA_5, 0x1, 0x2, 0x3, 0x4, + txscript.OP_DATA_5, 0x1, 0x2, 0x3, 0x4, }, - scripttype: btcscript.NonStandardTy, + scripttype: txscript.NonStandardTy, }, } func testScriptType(t *testing.T, test *scriptTypeTest) { - scripttype := btcscript.GetScriptClass(test.script) + scripttype := txscript.GetScriptClass(test.script) if scripttype != test.scripttype { t.Errorf("%s: expected %s got %s", test.name, test.scripttype, scripttype) @@ -2386,8 +2386,8 @@ func TestIsPayToScriptHash(t *testing.T) { t.Parallel() for _, test := range scriptTypeTests { - shouldBe := (test.scripttype == btcscript.ScriptHashTy) - p2sh := btcscript.IsPayToScriptHash(test.script) + shouldBe := (test.scripttype == txscript.ScriptHashTy) + p2sh := txscript.IsPayToScriptHash(test.script) if p2sh != shouldBe { t.Errorf("%s: epxected p2sh %v, got %v", test.name, shouldBe, p2sh) @@ -2431,7 +2431,7 @@ func TestBadPC(t *testing.T) { }), Index: 0, }, - SignatureScript: []uint8{btcscript.OP_NOP}, + SignatureScript: []uint8{txscript.OP_NOP}, Sequence: 4294967295, }, }, @@ -2443,10 +2443,10 @@ func TestBadPC(t *testing.T) { }, LockTime: 0, } - pkScript := []byte{btcscript.OP_NOP} + pkScript := []byte{txscript.OP_NOP} for _, test := range pcTests { - engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript, + engine, err := txscript.NewScript(tx.TxIn[0].SignatureScript, pkScript, 0, tx, 0) if err != nil { t.Errorf("Failed to create script: %v", err) @@ -2505,20 +2505,20 @@ func TestCheckErrorCondition(t *testing.T) { LockTime: 0, } pkScript := []byte{ - btcscript.OP_NOP, - btcscript.OP_NOP, - btcscript.OP_NOP, - btcscript.OP_NOP, - btcscript.OP_NOP, - btcscript.OP_NOP, - btcscript.OP_NOP, - btcscript.OP_NOP, - btcscript.OP_NOP, - btcscript.OP_NOP, - btcscript.OP_TRUE, + txscript.OP_NOP, + txscript.OP_NOP, + txscript.OP_NOP, + txscript.OP_NOP, + txscript.OP_NOP, + txscript.OP_NOP, + txscript.OP_NOP, + txscript.OP_NOP, + txscript.OP_NOP, + txscript.OP_NOP, + txscript.OP_TRUE, } - engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript, pkScript, + engine, err := txscript.NewScript(tx.TxIn[0].SignatureScript, pkScript, 0, tx, 0) if err != nil { t.Errorf("failed to create script: %v", err) @@ -2536,7 +2536,7 @@ func TestCheckErrorCondition(t *testing.T) { } err = engine.CheckErrorCondition() - if err != btcscript.ErrStackScriptUnfinished { + if err != txscript.ErrStackScriptUnfinished { t.Errorf("got unexepected error %v on %dth iteration", err, i) return @@ -2561,7 +2561,7 @@ func TestCheckErrorCondition(t *testing.T) { type TstSigScript struct { name string inputs []TstInput - hashType btcscript.SigHashType + hashType txscript.SigHashType compress bool scriptAtWrongIndex bool } @@ -2620,7 +2620,7 @@ var SigScriptTests = []TstSigScript{ indexOutOfRange: false, }, }, - hashType: btcscript.SigHashAll, + hashType: txscript.SigHashAll, compress: false, scriptAtWrongIndex: false, }, @@ -2640,7 +2640,7 @@ var SigScriptTests = []TstSigScript{ indexOutOfRange: false, }, }, - hashType: btcscript.SigHashAll, + hashType: txscript.SigHashAll, compress: false, scriptAtWrongIndex: false, }, @@ -2654,7 +2654,7 @@ var SigScriptTests = []TstSigScript{ indexOutOfRange: false, }, }, - hashType: btcscript.SigHashAll, + hashType: txscript.SigHashAll, compress: true, scriptAtWrongIndex: false, }, @@ -2674,7 +2674,7 @@ var SigScriptTests = []TstSigScript{ indexOutOfRange: false, }, }, - hashType: btcscript.SigHashAll, + hashType: txscript.SigHashAll, compress: true, scriptAtWrongIndex: false, }, @@ -2688,7 +2688,7 @@ var SigScriptTests = []TstSigScript{ indexOutOfRange: false, }, }, - hashType: btcscript.SigHashNone, + hashType: txscript.SigHashNone, compress: false, scriptAtWrongIndex: false, }, @@ -2702,7 +2702,7 @@ var SigScriptTests = []TstSigScript{ indexOutOfRange: false, }, }, - hashType: btcscript.SigHashSingle, + hashType: txscript.SigHashSingle, compress: false, scriptAtWrongIndex: false, }, @@ -2716,7 +2716,7 @@ var SigScriptTests = []TstSigScript{ indexOutOfRange: false, }, }, - hashType: btcscript.SigHashAnyOneCanPay, + hashType: txscript.SigHashAnyOneCanPay, compress: false, scriptAtWrongIndex: false, }, @@ -2744,7 +2744,7 @@ var SigScriptTests = []TstSigScript{ indexOutOfRange: false, }, }, - hashType: btcscript.SigHashAll, + hashType: txscript.SigHashAll, compress: true, scriptAtWrongIndex: false, }, @@ -2757,7 +2757,7 @@ var SigScriptTests = []TstSigScript{ indexOutOfRange: false, }, }, - hashType: btcscript.SigHashAll, + hashType: txscript.SigHashAll, compress: false, scriptAtWrongIndex: false, }, @@ -2777,7 +2777,7 @@ var SigScriptTests = []TstSigScript{ indexOutOfRange: false, }, }, - hashType: btcscript.SigHashAll, + hashType: txscript.SigHashAll, compress: false, scriptAtWrongIndex: true, }, @@ -2797,7 +2797,7 @@ var SigScriptTests = []TstSigScript{ indexOutOfRange: false, }, }, - hashType: btcscript.SigHashAll, + hashType: txscript.SigHashAll, compress: false, scriptAtWrongIndex: true, }, @@ -2817,7 +2817,7 @@ nexttest: for i := range SigScriptTests { tx := btcwire.NewMsgTx() - output := btcwire.NewTxOut(500, []byte{btcscript.OP_RETURN}) + output := btcwire.NewTxOut(500, []byte{txscript.OP_RETURN}) tx.AddTxOut(output) for _ = range SigScriptTests[i].inputs { @@ -2835,7 +2835,7 @@ nexttest: } else { idx = j } - script, err = btcscript.SignatureScript(tx, idx, + script, err = txscript.SignatureScript(tx, idx, SigScriptTests[i].inputs[j].txout.PkScript, SigScriptTests[i].hashType, privKey, SigScriptTests[i].compress) @@ -2867,9 +2867,9 @@ nexttest: } // Validate tx input scripts - scriptFlags := btcscript.ScriptBip16 | btcscript.ScriptCanonicalSignatures + scriptFlags := txscript.ScriptBip16 | txscript.ScriptCanonicalSignatures for j, txin := range tx.TxIn { - engine, err := btcscript.NewScript(txin.SignatureScript, + engine, err := txscript.NewScript(txin.SignatureScript, SigScriptTests[i].inputs[j].txout.PkScript, j, tx, scriptFlags) if err != nil { @@ -2897,42 +2897,42 @@ func TestStringifyClass(t *testing.T) { tests := []struct { name string - scriptclass btcscript.ScriptClass + scriptclass txscript.ScriptClass stringed string }{ { name: "nonstandardty", - scriptclass: btcscript.NonStandardTy, + scriptclass: txscript.NonStandardTy, stringed: "nonstandard", }, { name: "pubkey", - scriptclass: btcscript.PubKeyTy, + scriptclass: txscript.PubKeyTy, stringed: "pubkey", }, { name: "pubkeyhash", - scriptclass: btcscript.PubKeyHashTy, + scriptclass: txscript.PubKeyHashTy, stringed: "pubkeyhash", }, { name: "scripthash", - scriptclass: btcscript.ScriptHashTy, + scriptclass: txscript.ScriptHashTy, stringed: "scripthash", }, { name: "multisigty", - scriptclass: btcscript.MultiSigTy, + scriptclass: txscript.MultiSigTy, stringed: "multisig", }, { name: "nulldataty", - scriptclass: btcscript.NullDataTy, + scriptclass: txscript.NullDataTy, stringed: "nulldata", }, { name: "broken", - scriptclass: btcscript.ScriptClass(255), + scriptclass: txscript.ScriptClass(255), stringed: "Invalid", }, } @@ -3063,12 +3063,12 @@ func TestPayToAddrScript(t *testing.T) { { p2pkCompressedMain, []byte{ - btcscript.OP_DATA_33, + txscript.OP_DATA_33, 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, 0x52, 0xc6, - 0xb4, btcscript.OP_CHECKSIG, + 0xb4, txscript.OP_CHECKSIG, }, nil, }, @@ -3076,12 +3076,12 @@ func TestPayToAddrScript(t *testing.T) { { p2pkCompressed2Main, []byte{ - btcscript.OP_DATA_33, + txscript.OP_DATA_33, 0x03, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, 0xb1, 0x6e, - 0x65, btcscript.OP_CHECKSIG, + 0x65, txscript.OP_CHECKSIG, }, nil, }, @@ -3089,7 +3089,7 @@ func TestPayToAddrScript(t *testing.T) { { p2pkUncompressedMain, []byte{ - btcscript.OP_DATA_65, + txscript.OP_DATA_65, 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, @@ -3098,23 +3098,23 @@ func TestPayToAddrScript(t *testing.T) { 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, - 0xa3, btcscript.OP_CHECKSIG, + 0xa3, txscript.OP_CHECKSIG, }, nil, }, // Supported address types with nil pointers. - {(*btcutil.AddressPubKeyHash)(nil), []byte{}, btcscript.ErrUnsupportedAddress}, - {(*btcutil.AddressScriptHash)(nil), []byte{}, btcscript.ErrUnsupportedAddress}, - {(*btcutil.AddressPubKey)(nil), []byte{}, btcscript.ErrUnsupportedAddress}, + {(*btcutil.AddressPubKeyHash)(nil), []byte{}, txscript.ErrUnsupportedAddress}, + {(*btcutil.AddressScriptHash)(nil), []byte{}, txscript.ErrUnsupportedAddress}, + {(*btcutil.AddressPubKey)(nil), []byte{}, txscript.ErrUnsupportedAddress}, // Unsupported address type. - {&bogusAddress{}, []byte{}, btcscript.ErrUnsupportedAddress}, + {&bogusAddress{}, []byte{}, txscript.ErrUnsupportedAddress}, } t.Logf("Running %d tests", len(tests)) for i, test := range tests { - pkScript, err := btcscript.PayToAddrScript(test.in) + pkScript, err := txscript.PayToAddrScript(test.in) if err != test.err { t.Errorf("PayToAddrScript #%d unexpected error - "+ "got %v, want %v", i, err, test.err) @@ -3181,20 +3181,20 @@ func TestMultiSigScript(t *testing.T) { }, 1, []byte{ - btcscript.OP_1, - btcscript.OP_DATA_33, + txscript.OP_1, + txscript.OP_DATA_33, 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, 0x52, 0xc6, 0xb4, - btcscript.OP_DATA_33, + txscript.OP_DATA_33, 0x03, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, 0xb1, 0x6e, 0x65, - btcscript.OP_2, btcscript.OP_CHECKMULTISIG, + txscript.OP_2, txscript.OP_CHECKMULTISIG, }, nil, }, @@ -3205,20 +3205,20 @@ func TestMultiSigScript(t *testing.T) { }, 2, []byte{ - btcscript.OP_2, - btcscript.OP_DATA_33, + txscript.OP_2, + txscript.OP_DATA_33, 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, 0x52, 0xc6, 0xb4, - btcscript.OP_DATA_33, + txscript.OP_DATA_33, 0x03, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, 0xb1, 0x6e, 0x65, - btcscript.OP_2, btcscript.OP_CHECKMULTISIG, + txscript.OP_2, txscript.OP_CHECKMULTISIG, }, nil, }, @@ -3229,7 +3229,7 @@ func TestMultiSigScript(t *testing.T) { }, 3, []byte{}, - btcscript.ErrBadNumRequired, + txscript.ErrBadNumRequired, }, { []*btcutil.AddressPubKey{ @@ -3237,7 +3237,7 @@ func TestMultiSigScript(t *testing.T) { }, 1, []byte{ - btcscript.OP_1, btcscript.OP_DATA_65, + txscript.OP_1, txscript.OP_DATA_65, 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, @@ -3247,7 +3247,7 @@ func TestMultiSigScript(t *testing.T) { 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, 0xa3, - btcscript.OP_1, btcscript.OP_CHECKMULTISIG, + txscript.OP_1, txscript.OP_CHECKMULTISIG, }, nil, }, @@ -3257,13 +3257,13 @@ func TestMultiSigScript(t *testing.T) { }, 2, []byte{}, - btcscript.ErrBadNumRequired, + txscript.ErrBadNumRequired, }, } t.Logf("Running %d tests", len(tests)) for i, test := range tests { - script, err := btcscript.MultiSigScript(test.keys, + script, err := txscript.MultiSigScript(test.keys, test.nrequired) if err != test.err { t.Errorf("MultiSigScript #%d unexpected error - "+ @@ -3280,10 +3280,10 @@ func TestMultiSigScript(t *testing.T) { } func signAndCheck(msg string, tx *btcwire.MsgTx, idx int, pkScript []byte, - hashType btcscript.SigHashType, kdb btcscript.KeyDB, sdb btcscript.ScriptDB, + hashType txscript.SigHashType, kdb txscript.KeyDB, sdb txscript.ScriptDB, previousScript []byte) error { - sigScript, err := btcscript.SignTxOutput( + sigScript, err := txscript.SignTxOutput( &btcnet.TestNet3Params, tx, idx, pkScript, hashType, kdb, sdb, []byte{}) if err != nil { @@ -3295,9 +3295,9 @@ func signAndCheck(msg string, tx *btcwire.MsgTx, idx int, pkScript []byte, func checkScripts(msg string, tx *btcwire.MsgTx, idx int, sigScript, pkScript []byte) error { - engine, err := btcscript.NewScript(sigScript, pkScript, idx, tx, - btcscript.ScriptBip16| - btcscript.ScriptCanonicalSignatures) + engine, err := txscript.NewScript(sigScript, pkScript, idx, tx, + txscript.ScriptBip16| + txscript.ScriptCanonicalSignatures) if err != nil { return fmt.Errorf("failed to make script engine for %s: %v", msg, err) @@ -3317,14 +3317,14 @@ type addressToKey struct { compressed bool } -func mkGetKey(keys map[string]addressToKey) btcscript.KeyDB { +func mkGetKey(keys map[string]addressToKey) txscript.KeyDB { if keys == nil { - return btcscript.KeyClosure(func(addr btcutil.Address) (*btcec.PrivateKey, + return txscript.KeyClosure(func(addr btcutil.Address) (*btcec.PrivateKey, bool, error) { return nil, false, errors.New("nope") }) } - return btcscript.KeyClosure(func(addr btcutil.Address) (*btcec.PrivateKey, + return txscript.KeyClosure(func(addr btcutil.Address) (*btcec.PrivateKey, bool, error) { a2k, ok := keys[addr.EncodeAddress()] if !ok { @@ -3334,14 +3334,14 @@ func mkGetKey(keys map[string]addressToKey) btcscript.KeyDB { }) } -func mkGetScript(scripts map[string][]byte) btcscript.ScriptDB { +func mkGetScript(scripts map[string][]byte) txscript.ScriptDB { if scripts == nil { - return btcscript.ScriptClosure(func(addr btcutil.Address) ( + return txscript.ScriptClosure(func(addr btcutil.Address) ( []byte, error) { return nil, errors.New("nope") }) } - return btcscript.ScriptClosure(func(addr btcutil.Address) ([]byte, + return txscript.ScriptClosure(func(addr btcutil.Address) ([]byte, error) { script, ok := scripts[addr.EncodeAddress()] if !ok { @@ -3357,14 +3357,14 @@ func TestSignTxOutput(t *testing.T) { // make key // make script based on key. // sign with magic pixie dust. - hashTypes := []btcscript.SigHashType{ - btcscript.SigHashOld, // no longer used but should act like all - btcscript.SigHashAll, - btcscript.SigHashNone, - btcscript.SigHashSingle, - btcscript.SigHashAll | btcscript.SigHashAnyOneCanPay, - btcscript.SigHashNone | btcscript.SigHashAnyOneCanPay, - btcscript.SigHashSingle | btcscript.SigHashAnyOneCanPay, + hashTypes := []txscript.SigHashType{ + txscript.SigHashOld, // no longer used but should act like all + txscript.SigHashAll, + txscript.SigHashNone, + txscript.SigHashSingle, + txscript.SigHashAll | txscript.SigHashAnyOneCanPay, + txscript.SigHashNone | txscript.SigHashAnyOneCanPay, + txscript.SigHashSingle | txscript.SigHashAnyOneCanPay, } tx := &btcwire.MsgTx{ Version: 1, @@ -3426,7 +3426,7 @@ func TestSignTxOutput(t *testing.T) { break } - pkScript, err := btcscript.PayToAddrScript(address) + pkScript, err := txscript.PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) @@ -3463,13 +3463,13 @@ func TestSignTxOutput(t *testing.T) { break } - pkScript, err := btcscript.PayToAddrScript(address) + pkScript, err := txscript.PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) } - sigScript, err := btcscript.SignTxOutput( + sigScript, err := txscript.SignTxOutput( &btcnet.TestNet3Params, tx, i, pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, @@ -3482,7 +3482,7 @@ func TestSignTxOutput(t *testing.T) { // by the above loop, this should be valid, now sign // again and merge. - sigScript, err = btcscript.SignTxOutput( + sigScript, err = txscript.SignTxOutput( &btcnet.TestNet3Params, tx, i, pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, @@ -3524,7 +3524,7 @@ func TestSignTxOutput(t *testing.T) { break } - pkScript, err := btcscript.PayToAddrScript(address) + pkScript, err := txscript.PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) @@ -3562,13 +3562,13 @@ func TestSignTxOutput(t *testing.T) { break } - pkScript, err := btcscript.PayToAddrScript(address) + pkScript, err := txscript.PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) } - sigScript, err := btcscript.SignTxOutput( + sigScript, err := txscript.SignTxOutput( &btcnet.TestNet3Params, tx, i, pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, @@ -3581,7 +3581,7 @@ func TestSignTxOutput(t *testing.T) { // by the above loop, this should be valid, now sign // again and merge. - sigScript, err = btcscript.SignTxOutput( + sigScript, err = txscript.SignTxOutput( &btcnet.TestNet3Params, tx, i, pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, @@ -3623,7 +3623,7 @@ func TestSignTxOutput(t *testing.T) { break } - pkScript, err := btcscript.PayToAddrScript(address) + pkScript, err := txscript.PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) @@ -3661,13 +3661,13 @@ func TestSignTxOutput(t *testing.T) { break } - pkScript, err := btcscript.PayToAddrScript(address) + pkScript, err := txscript.PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) } - sigScript, err := btcscript.SignTxOutput( + sigScript, err := txscript.SignTxOutput( &btcnet.TestNet3Params, tx, i, pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, @@ -3680,7 +3680,7 @@ func TestSignTxOutput(t *testing.T) { // by the above loop, this should be valid, now sign // again and merge. - sigScript, err = btcscript.SignTxOutput( + sigScript, err = txscript.SignTxOutput( &btcnet.TestNet3Params, tx, i, pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, @@ -3722,7 +3722,7 @@ func TestSignTxOutput(t *testing.T) { break } - pkScript, err := btcscript.PayToAddrScript(address) + pkScript, err := txscript.PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) @@ -3760,13 +3760,13 @@ func TestSignTxOutput(t *testing.T) { break } - pkScript, err := btcscript.PayToAddrScript(address) + pkScript, err := txscript.PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) } - sigScript, err := btcscript.SignTxOutput( + sigScript, err := txscript.SignTxOutput( &btcnet.TestNet3Params, tx, i, pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, @@ -3779,7 +3779,7 @@ func TestSignTxOutput(t *testing.T) { // by the above loop, this should be valid, now sign // again and merge. - sigScript, err = btcscript.SignTxOutput( + sigScript, err = txscript.SignTxOutput( &btcnet.TestNet3Params, tx, i, pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, @@ -3821,7 +3821,7 @@ func TestSignTxOutput(t *testing.T) { break } - pkScript, err := btcscript.PayToAddrScript(address) + pkScript, err := txscript.PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) @@ -3836,7 +3836,7 @@ func TestSignTxOutput(t *testing.T) { break } - scriptPkScript, err := btcscript.PayToAddrScript( + scriptPkScript, err := txscript.PayToAddrScript( scriptAddr) if err != nil { t.Errorf("failed to make script pkscript for "+ @@ -3878,7 +3878,7 @@ func TestSignTxOutput(t *testing.T) { break } - pkScript, err := btcscript.PayToAddrScript(address) + pkScript, err := txscript.PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) @@ -3893,7 +3893,7 @@ func TestSignTxOutput(t *testing.T) { break } - scriptPkScript, err := btcscript.PayToAddrScript( + scriptPkScript, err := txscript.PayToAddrScript( scriptAddr) if err != nil { t.Errorf("failed to make script pkscript for "+ @@ -3901,7 +3901,7 @@ func TestSignTxOutput(t *testing.T) { break } - sigScript, err := btcscript.SignTxOutput( + sigScript, err := txscript.SignTxOutput( &btcnet.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, @@ -3916,7 +3916,7 @@ func TestSignTxOutput(t *testing.T) { // by the above loop, this should be valid, now sign // again and merge. - sigScript, err = btcscript.SignTxOutput( + sigScript, err = txscript.SignTxOutput( &btcnet.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, @@ -3960,7 +3960,7 @@ func TestSignTxOutput(t *testing.T) { break } - pkScript, err := btcscript.PayToAddrScript(address) + pkScript, err := txscript.PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) @@ -3974,7 +3974,7 @@ func TestSignTxOutput(t *testing.T) { break } - scriptPkScript, err := btcscript.PayToAddrScript( + scriptPkScript, err := txscript.PayToAddrScript( scriptAddr) if err != nil { t.Errorf("failed to make script pkscript for "+ @@ -4017,7 +4017,7 @@ func TestSignTxOutput(t *testing.T) { break } - pkScript, err := btcscript.PayToAddrScript(address) + pkScript, err := txscript.PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) @@ -4031,7 +4031,7 @@ func TestSignTxOutput(t *testing.T) { break } - scriptPkScript, err := btcscript.PayToAddrScript( + scriptPkScript, err := txscript.PayToAddrScript( scriptAddr) if err != nil { t.Errorf("failed to make script pkscript for "+ @@ -4039,7 +4039,7 @@ func TestSignTxOutput(t *testing.T) { break } - sigScript, err := btcscript.SignTxOutput( + sigScript, err := txscript.SignTxOutput( &btcnet.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, @@ -4054,7 +4054,7 @@ func TestSignTxOutput(t *testing.T) { // by the above loop, this should be valid, now sign // again and merge. - sigScript, err = btcscript.SignTxOutput( + sigScript, err = txscript.SignTxOutput( &btcnet.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, @@ -4098,7 +4098,7 @@ func TestSignTxOutput(t *testing.T) { break } - pkScript, err := btcscript.PayToAddrScript(address) + pkScript, err := txscript.PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) @@ -4112,7 +4112,7 @@ func TestSignTxOutput(t *testing.T) { break } - scriptPkScript, err := btcscript.PayToAddrScript( + scriptPkScript, err := txscript.PayToAddrScript( scriptAddr) if err != nil { t.Errorf("failed to make script pkscript for "+ @@ -4155,7 +4155,7 @@ func TestSignTxOutput(t *testing.T) { break } - pkScript, err := btcscript.PayToAddrScript(address) + pkScript, err := txscript.PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) @@ -4169,7 +4169,7 @@ func TestSignTxOutput(t *testing.T) { break } - scriptPkScript, err := btcscript.PayToAddrScript( + scriptPkScript, err := txscript.PayToAddrScript( scriptAddr) if err != nil { t.Errorf("failed to make script pkscript for "+ @@ -4177,7 +4177,7 @@ func TestSignTxOutput(t *testing.T) { break } - sigScript, err := btcscript.SignTxOutput( + sigScript, err := txscript.SignTxOutput( &btcnet.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, @@ -4192,7 +4192,7 @@ func TestSignTxOutput(t *testing.T) { // by the above loop, this should be valid, now sign // again and merge. - sigScript, err = btcscript.SignTxOutput( + sigScript, err = txscript.SignTxOutput( &btcnet.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, @@ -4236,7 +4236,7 @@ func TestSignTxOutput(t *testing.T) { break } - pkScript, err := btcscript.PayToAddrScript(address) + pkScript, err := txscript.PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) @@ -4250,7 +4250,7 @@ func TestSignTxOutput(t *testing.T) { break } - scriptPkScript, err := btcscript.PayToAddrScript( + scriptPkScript, err := txscript.PayToAddrScript( scriptAddr) if err != nil { t.Errorf("failed to make script pkscript for "+ @@ -4293,7 +4293,7 @@ func TestSignTxOutput(t *testing.T) { break } - pkScript, err := btcscript.PayToAddrScript(address) + pkScript, err := txscript.PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) @@ -4307,7 +4307,7 @@ func TestSignTxOutput(t *testing.T) { break } - scriptPkScript, err := btcscript.PayToAddrScript( + scriptPkScript, err := txscript.PayToAddrScript( scriptAddr) if err != nil { t.Errorf("failed to make script pkscript for "+ @@ -4315,7 +4315,7 @@ func TestSignTxOutput(t *testing.T) { break } - sigScript, err := btcscript.SignTxOutput( + sigScript, err := txscript.SignTxOutput( &btcnet.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, @@ -4330,7 +4330,7 @@ func TestSignTxOutput(t *testing.T) { // by the above loop, this should be valid, now sign // again and merge. - sigScript, err = btcscript.SignTxOutput( + sigScript, err = txscript.SignTxOutput( &btcnet.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, @@ -4391,7 +4391,7 @@ func TestSignTxOutput(t *testing.T) { break } - pkScript, err := btcscript.MultiSigScript( + pkScript, err := txscript.MultiSigScript( []*btcutil.AddressPubKey{address1, address2}, 2) if err != nil { @@ -4407,7 +4407,7 @@ func TestSignTxOutput(t *testing.T) { break } - scriptPkScript, err := btcscript.PayToAddrScript( + scriptPkScript, err := txscript.PayToAddrScript( scriptAddr) if err != nil { t.Errorf("failed to make script pkscript for "+ @@ -4468,7 +4468,7 @@ func TestSignTxOutput(t *testing.T) { break } - pkScript, err := btcscript.MultiSigScript( + pkScript, err := txscript.MultiSigScript( []*btcutil.AddressPubKey{address1, address2}, 2) if err != nil { @@ -4484,7 +4484,7 @@ func TestSignTxOutput(t *testing.T) { break } - scriptPkScript, err := btcscript.PayToAddrScript( + scriptPkScript, err := txscript.PayToAddrScript( scriptAddr) if err != nil { t.Errorf("failed to make script pkscript for "+ @@ -4492,7 +4492,7 @@ func TestSignTxOutput(t *testing.T) { break } - sigScript, err := btcscript.SignTxOutput( + sigScript, err := txscript.SignTxOutput( &btcnet.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address1.EncodeAddress(): {key1, true}, @@ -4513,7 +4513,7 @@ func TestSignTxOutput(t *testing.T) { } // Sign with the other key and merge - sigScript, err = btcscript.SignTxOutput( + sigScript, err = txscript.SignTxOutput( &btcnet.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address2.EncodeAddress(): {key2, true}, @@ -4575,7 +4575,7 @@ func TestSignTxOutput(t *testing.T) { break } - pkScript, err := btcscript.MultiSigScript( + pkScript, err := txscript.MultiSigScript( []*btcutil.AddressPubKey{address1, address2}, 2) if err != nil { @@ -4591,7 +4591,7 @@ func TestSignTxOutput(t *testing.T) { break } - scriptPkScript, err := btcscript.PayToAddrScript( + scriptPkScript, err := txscript.PayToAddrScript( scriptAddr) if err != nil { t.Errorf("failed to make script pkscript for "+ @@ -4599,7 +4599,7 @@ func TestSignTxOutput(t *testing.T) { break } - sigScript, err := btcscript.SignTxOutput( + sigScript, err := txscript.SignTxOutput( &btcnet.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address1.EncodeAddress(): {key1, true}, @@ -4620,7 +4620,7 @@ func TestSignTxOutput(t *testing.T) { } // Sign with the other key and merge - sigScript, err = btcscript.SignTxOutput( + sigScript, err = txscript.SignTxOutput( &btcnet.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address1.EncodeAddress(): {key1, true}, @@ -4661,13 +4661,13 @@ func TestCalcMultiSigStats(t *testing.T) { 0x71, 0x05, 0xcd, 0x6a, 0x82, 0x8e, 0x03, 0x90, 0x9a, 0x67, 0x96, 0x2e, 0x0e, 0xa1, 0xf6, 0x1d, }, - expected: btcscript.ErrStackShortScript, + expected: txscript.ErrStackShortScript, }, { name: "stack underflow", script: []byte{ - btcscript.OP_RETURN, - btcscript.OP_PUSHDATA1, + txscript.OP_RETURN, + txscript.OP_PUSHDATA1, 0x29, 0x04, 0x67, 0x08, 0xaf, 0xdb, 0x0f, 0xe5, 0x54, 0x82, 0x71, 0x96, 0x7f, 0x1a, 0x67, 0x13, 0x0b, @@ -4676,13 +4676,13 @@ func TestCalcMultiSigStats(t *testing.T) { 0xeb, 0x64, 0x9f, 0x6b, 0xc3, 0xf4, 0xce, 0xf3, 0x08, }, - expected: btcscript.ErrStackUnderflow, + expected: txscript.ErrStackUnderflow, }, { name: "multisig script", script: []uint8{ - btcscript.OP_FALSE, - btcscript.OP_DATA_72, + txscript.OP_FALSE, + txscript.OP_DATA_72, 0x30, 0x45, 0x02, 0x20, 0x10, 0x6a, 0x3e, 0x4e, 0xf0, 0xb5, 0x1b, 0x76, 0x4a, 0x28, 0x87, @@ -4698,9 +4698,9 @@ func TestCalcMultiSigStats(t *testing.T) { 0x1f, 0xe0, 0x72, 0x82, 0xe3, 0xb6, 0xec, 0xb5, 0xf3, 0xbb, 0x28, 0x01, - btcscript.OP_CODESEPARATOR, - btcscript.OP_TRUE, - btcscript.OP_DATA_33, + txscript.OP_CODESEPARATOR, + txscript.OP_TRUE, + txscript.OP_DATA_33, 0x02, 0x32, 0xab, 0xdc, 0x89, 0x3e, 0x7f, 0x06, 0x31, 0x36, 0x4d, 0x7f, 0xd0, 0x1c, 0xb3, @@ -4708,15 +4708,15 @@ func TestCalcMultiSigStats(t *testing.T) { 0x9a, 0x00, 0x35, 0x7b, 0x3a, 0x78, 0x86, 0x21, 0x1a, 0xb4, 0x14, 0xd5, 0x5a, - btcscript.OP_TRUE, - btcscript.OP_CHECKMULTISIG, + txscript.OP_TRUE, + txscript.OP_CHECKMULTISIG, }, expected: nil, }, } for i, test := range tests { - if _, _, err := btcscript.CalcMultiSigStats(test.script); err != test.expected { + if _, _, err := txscript.CalcMultiSigStats(test.script); err != test.expected { t.Errorf("CalcMultiSigStats #%d (%s) wrong result\n"+ "got: %x\nwant: %x", i, test.name, err, test.expected) @@ -4744,13 +4744,13 @@ func TestHasCanonicalPushes(t *testing.T) { }, { name: "non-canonical push", - script: []byte{btcscript.OP_PUSHDATA1, 4, 1, 2, 3, 4}, + script: []byte{txscript.OP_PUSHDATA1, 4, 1, 2, 3, 4}, expected: false, }, } for i, test := range tests { - if btcscript.HasCanonicalPushes(test.script) != test.expected { + if txscript.HasCanonicalPushes(test.script) != test.expected { t.Errorf("HasCanonicalPushes #%d (%s) wrong result\n"+ "got: %v\nwant: %v", i, test.name, true, test.expected) @@ -4776,7 +4776,7 @@ func TestIsPushOnlyScript(t *testing.T) { expected: false, } - if btcscript.IsPushOnlyScript(test.script) != test.expected { + if txscript.IsPushOnlyScript(test.script) != test.expected { t.Errorf("IsPushOnlyScript (%s) wrong result\n"+ "got: %v\nwant: %v", test.name, true, test.expected) diff --git a/scriptbuilder.go b/txscript/scriptbuilder.go similarity index 97% rename from scriptbuilder.go rename to txscript/scriptbuilder.go index 566189df..3149b8d7 100644 --- a/scriptbuilder.go +++ b/txscript/scriptbuilder.go @@ -1,8 +1,8 @@ -// Copyright (c) 2013-2014 Conformal Systems LLC. +// Copyright (c) 2013-2015 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. -package btcscript +package txscript import ( "encoding/binary" @@ -38,10 +38,10 @@ func (e ErrScriptNotCanonical) Error() string { // For example, the following would build a 2-of-3 multisig script for usage in // a pay-to-script-hash (although in this situation MultiSigScript() would be a // better choice to generate the script): -// builder := btcscript.NewScriptBuilder() -// builder.AddOp(btcscript.OP_2).AddData(pubKey1).AddData(pubKey2) -// builder.AddData(pubKey3).AddOp(btcscript.OP_3) -// builder.AddOp(btcscript.OP_CHECKMULTISIG) +// builder := txscript.NewScriptBuilder() +// builder.AddOp(txscript.OP_2).AddData(pubKey1).AddData(pubKey2) +// builder.AddData(pubKey3).AddOp(txscript.OP_3) +// builder.AddOp(txscript.OP_CHECKMULTISIG) // script, err := builder.Script() // if err != nil { // // Handle the error. diff --git a/scriptbuilder_test.go b/txscript/scriptbuilder_test.go similarity index 61% rename from scriptbuilder_test.go rename to txscript/scriptbuilder_test.go index 198dfda2..296a1342 100644 --- a/scriptbuilder_test.go +++ b/txscript/scriptbuilder_test.go @@ -1,14 +1,14 @@ -// Copyright (c) 2013-2014 Conformal Systems LLC. +// Copyright (c) 2013-2015 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. -package btcscript_test +package txscript_test import ( "bytes" "testing" - "github.com/btcsuite/btcscript" + "github.com/btcsuite/btcd/txscript" ) // TestScriptBuilderAddOp tests that pushing opcodes to a script via the @@ -23,22 +23,22 @@ func TestScriptBuilderAddOp(t *testing.T) { }{ { name: "push OP_0", - opcodes: []byte{btcscript.OP_0}, - expected: []byte{btcscript.OP_0}, + opcodes: []byte{txscript.OP_0}, + expected: []byte{txscript.OP_0}, }, { name: "push OP_1 OP_2", - opcodes: []byte{btcscript.OP_1, btcscript.OP_2}, - expected: []byte{btcscript.OP_1, btcscript.OP_2}, + opcodes: []byte{txscript.OP_1, txscript.OP_2}, + expected: []byte{txscript.OP_1, txscript.OP_2}, }, { name: "push OP_HASH160 OP_EQUAL", - opcodes: []byte{btcscript.OP_HASH160, btcscript.OP_EQUAL}, - expected: []byte{btcscript.OP_HASH160, btcscript.OP_EQUAL}, + opcodes: []byte{txscript.OP_HASH160, txscript.OP_EQUAL}, + expected: []byte{txscript.OP_HASH160, txscript.OP_EQUAL}, }, } - builder := btcscript.NewScriptBuilder() + builder := txscript.NewScriptBuilder() t.Logf("Running %d tests", len(tests)) for i, test := range tests { builder.Reset() @@ -70,47 +70,47 @@ func TestScriptBuilderAddInt64(t *testing.T) { val int64 expected []byte }{ - {name: "push -1", val: -1, expected: []byte{btcscript.OP_1NEGATE}}, - {name: "push small int 0", val: 0, expected: []byte{btcscript.OP_0}}, - {name: "push small int 1", val: 1, expected: []byte{btcscript.OP_1}}, - {name: "push small int 2", val: 2, expected: []byte{btcscript.OP_2}}, - {name: "push small int 3", val: 3, expected: []byte{btcscript.OP_3}}, - {name: "push small int 4", val: 4, expected: []byte{btcscript.OP_4}}, - {name: "push small int 5", val: 5, expected: []byte{btcscript.OP_5}}, - {name: "push small int 6", val: 6, expected: []byte{btcscript.OP_6}}, - {name: "push small int 7", val: 7, expected: []byte{btcscript.OP_7}}, - {name: "push small int 8", val: 8, expected: []byte{btcscript.OP_8}}, - {name: "push small int 9", val: 9, expected: []byte{btcscript.OP_9}}, - {name: "push small int 10", val: 10, expected: []byte{btcscript.OP_10}}, - {name: "push small int 11", val: 11, expected: []byte{btcscript.OP_11}}, - {name: "push small int 12", val: 12, expected: []byte{btcscript.OP_12}}, - {name: "push small int 13", val: 13, expected: []byte{btcscript.OP_13}}, - {name: "push small int 14", val: 14, expected: []byte{btcscript.OP_14}}, - {name: "push small int 15", val: 15, expected: []byte{btcscript.OP_15}}, - {name: "push small int 16", val: 16, expected: []byte{btcscript.OP_16}}, - {name: "push 17", val: 17, expected: []byte{btcscript.OP_DATA_1, 0x11}}, - {name: "push 65", val: 65, expected: []byte{btcscript.OP_DATA_1, 0x41}}, - {name: "push 127", val: 127, expected: []byte{btcscript.OP_DATA_1, 0x7f}}, - {name: "push 128", val: 128, expected: []byte{btcscript.OP_DATA_2, 0x80, 0}}, - {name: "push 255", val: 255, expected: []byte{btcscript.OP_DATA_2, 0xff, 0}}, - {name: "push 256", val: 256, expected: []byte{btcscript.OP_DATA_2, 0, 0x01}}, - {name: "push 32767", val: 32767, expected: []byte{btcscript.OP_DATA_2, 0xff, 0x7f}}, - {name: "push 32768", val: 32768, expected: []byte{btcscript.OP_DATA_3, 0, 0x80, 0}}, - {name: "push -2", val: -2, expected: []byte{btcscript.OP_DATA_1, 0x82}}, - {name: "push -3", val: -3, expected: []byte{btcscript.OP_DATA_1, 0x83}}, - {name: "push -4", val: -4, expected: []byte{btcscript.OP_DATA_1, 0x84}}, - {name: "push -5", val: -5, expected: []byte{btcscript.OP_DATA_1, 0x85}}, - {name: "push -17", val: -17, expected: []byte{btcscript.OP_DATA_1, 0x91}}, - {name: "push -65", val: -65, expected: []byte{btcscript.OP_DATA_1, 0xc1}}, - {name: "push -127", val: -127, expected: []byte{btcscript.OP_DATA_1, 0xff}}, - {name: "push -128", val: -128, expected: []byte{btcscript.OP_DATA_2, 0x80, 0x80}}, - {name: "push -255", val: -255, expected: []byte{btcscript.OP_DATA_2, 0xff, 0x80}}, - {name: "push -256", val: -256, expected: []byte{btcscript.OP_DATA_2, 0x00, 0x81}}, - {name: "push -32767", val: -32767, expected: []byte{btcscript.OP_DATA_2, 0xff, 0xff}}, - {name: "push -32768", val: -32768, expected: []byte{btcscript.OP_DATA_3, 0x00, 0x80, 0x80}}, + {name: "push -1", val: -1, expected: []byte{txscript.OP_1NEGATE}}, + {name: "push small int 0", val: 0, expected: []byte{txscript.OP_0}}, + {name: "push small int 1", val: 1, expected: []byte{txscript.OP_1}}, + {name: "push small int 2", val: 2, expected: []byte{txscript.OP_2}}, + {name: "push small int 3", val: 3, expected: []byte{txscript.OP_3}}, + {name: "push small int 4", val: 4, expected: []byte{txscript.OP_4}}, + {name: "push small int 5", val: 5, expected: []byte{txscript.OP_5}}, + {name: "push small int 6", val: 6, expected: []byte{txscript.OP_6}}, + {name: "push small int 7", val: 7, expected: []byte{txscript.OP_7}}, + {name: "push small int 8", val: 8, expected: []byte{txscript.OP_8}}, + {name: "push small int 9", val: 9, expected: []byte{txscript.OP_9}}, + {name: "push small int 10", val: 10, expected: []byte{txscript.OP_10}}, + {name: "push small int 11", val: 11, expected: []byte{txscript.OP_11}}, + {name: "push small int 12", val: 12, expected: []byte{txscript.OP_12}}, + {name: "push small int 13", val: 13, expected: []byte{txscript.OP_13}}, + {name: "push small int 14", val: 14, expected: []byte{txscript.OP_14}}, + {name: "push small int 15", val: 15, expected: []byte{txscript.OP_15}}, + {name: "push small int 16", val: 16, expected: []byte{txscript.OP_16}}, + {name: "push 17", val: 17, expected: []byte{txscript.OP_DATA_1, 0x11}}, + {name: "push 65", val: 65, expected: []byte{txscript.OP_DATA_1, 0x41}}, + {name: "push 127", val: 127, expected: []byte{txscript.OP_DATA_1, 0x7f}}, + {name: "push 128", val: 128, expected: []byte{txscript.OP_DATA_2, 0x80, 0}}, + {name: "push 255", val: 255, expected: []byte{txscript.OP_DATA_2, 0xff, 0}}, + {name: "push 256", val: 256, expected: []byte{txscript.OP_DATA_2, 0, 0x01}}, + {name: "push 32767", val: 32767, expected: []byte{txscript.OP_DATA_2, 0xff, 0x7f}}, + {name: "push 32768", val: 32768, expected: []byte{txscript.OP_DATA_3, 0, 0x80, 0}}, + {name: "push -2", val: -2, expected: []byte{txscript.OP_DATA_1, 0x82}}, + {name: "push -3", val: -3, expected: []byte{txscript.OP_DATA_1, 0x83}}, + {name: "push -4", val: -4, expected: []byte{txscript.OP_DATA_1, 0x84}}, + {name: "push -5", val: -5, expected: []byte{txscript.OP_DATA_1, 0x85}}, + {name: "push -17", val: -17, expected: []byte{txscript.OP_DATA_1, 0x91}}, + {name: "push -65", val: -65, expected: []byte{txscript.OP_DATA_1, 0xc1}}, + {name: "push -127", val: -127, expected: []byte{txscript.OP_DATA_1, 0xff}}, + {name: "push -128", val: -128, expected: []byte{txscript.OP_DATA_2, 0x80, 0x80}}, + {name: "push -255", val: -255, expected: []byte{txscript.OP_DATA_2, 0xff, 0x80}}, + {name: "push -256", val: -256, expected: []byte{txscript.OP_DATA_2, 0x00, 0x81}}, + {name: "push -32767", val: -32767, expected: []byte{txscript.OP_DATA_2, 0xff, 0xff}}, + {name: "push -32768", val: -32768, expected: []byte{txscript.OP_DATA_3, 0x00, 0x80, 0x80}}, } - builder := btcscript.NewScriptBuilder() + builder := txscript.NewScriptBuilder() t.Logf("Running %d tests", len(tests)) for i, test := range tests { builder.Reset().AddInt64(test.val) @@ -139,34 +139,34 @@ func TestScriptBuilderAddUint64(t *testing.T) { val uint64 expected []byte }{ - {name: "push small int 0", val: 0, expected: []byte{btcscript.OP_0}}, - {name: "push small int 1", val: 1, expected: []byte{btcscript.OP_1}}, - {name: "push small int 2", val: 2, expected: []byte{btcscript.OP_2}}, - {name: "push small int 3", val: 3, expected: []byte{btcscript.OP_3}}, - {name: "push small int 4", val: 4, expected: []byte{btcscript.OP_4}}, - {name: "push small int 5", val: 5, expected: []byte{btcscript.OP_5}}, - {name: "push small int 6", val: 6, expected: []byte{btcscript.OP_6}}, - {name: "push small int 7", val: 7, expected: []byte{btcscript.OP_7}}, - {name: "push small int 8", val: 8, expected: []byte{btcscript.OP_8}}, - {name: "push small int 9", val: 9, expected: []byte{btcscript.OP_9}}, - {name: "push small int 10", val: 10, expected: []byte{btcscript.OP_10}}, - {name: "push small int 11", val: 11, expected: []byte{btcscript.OP_11}}, - {name: "push small int 12", val: 12, expected: []byte{btcscript.OP_12}}, - {name: "push small int 13", val: 13, expected: []byte{btcscript.OP_13}}, - {name: "push small int 14", val: 14, expected: []byte{btcscript.OP_14}}, - {name: "push small int 15", val: 15, expected: []byte{btcscript.OP_15}}, - {name: "push small int 16", val: 16, expected: []byte{btcscript.OP_16}}, - {name: "push 17", val: 17, expected: []byte{btcscript.OP_DATA_1, 0x11}}, - {name: "push 65", val: 65, expected: []byte{btcscript.OP_DATA_1, 0x41}}, - {name: "push 127", val: 127, expected: []byte{btcscript.OP_DATA_1, 0x7f}}, - {name: "push 128", val: 128, expected: []byte{btcscript.OP_DATA_2, 0x80, 0}}, - {name: "push 255", val: 255, expected: []byte{btcscript.OP_DATA_2, 0xff, 0}}, - {name: "push 256", val: 256, expected: []byte{btcscript.OP_DATA_2, 0, 0x01}}, - {name: "push 32767", val: 32767, expected: []byte{btcscript.OP_DATA_2, 0xff, 0x7f}}, - {name: "push 32768", val: 32768, expected: []byte{btcscript.OP_DATA_3, 0, 0x80, 0}}, + {name: "push small int 0", val: 0, expected: []byte{txscript.OP_0}}, + {name: "push small int 1", val: 1, expected: []byte{txscript.OP_1}}, + {name: "push small int 2", val: 2, expected: []byte{txscript.OP_2}}, + {name: "push small int 3", val: 3, expected: []byte{txscript.OP_3}}, + {name: "push small int 4", val: 4, expected: []byte{txscript.OP_4}}, + {name: "push small int 5", val: 5, expected: []byte{txscript.OP_5}}, + {name: "push small int 6", val: 6, expected: []byte{txscript.OP_6}}, + {name: "push small int 7", val: 7, expected: []byte{txscript.OP_7}}, + {name: "push small int 8", val: 8, expected: []byte{txscript.OP_8}}, + {name: "push small int 9", val: 9, expected: []byte{txscript.OP_9}}, + {name: "push small int 10", val: 10, expected: []byte{txscript.OP_10}}, + {name: "push small int 11", val: 11, expected: []byte{txscript.OP_11}}, + {name: "push small int 12", val: 12, expected: []byte{txscript.OP_12}}, + {name: "push small int 13", val: 13, expected: []byte{txscript.OP_13}}, + {name: "push small int 14", val: 14, expected: []byte{txscript.OP_14}}, + {name: "push small int 15", val: 15, expected: []byte{txscript.OP_15}}, + {name: "push small int 16", val: 16, expected: []byte{txscript.OP_16}}, + {name: "push 17", val: 17, expected: []byte{txscript.OP_DATA_1, 0x11}}, + {name: "push 65", val: 65, expected: []byte{txscript.OP_DATA_1, 0x41}}, + {name: "push 127", val: 127, expected: []byte{txscript.OP_DATA_1, 0x7f}}, + {name: "push 128", val: 128, expected: []byte{txscript.OP_DATA_2, 0x80, 0}}, + {name: "push 255", val: 255, expected: []byte{txscript.OP_DATA_2, 0xff, 0}}, + {name: "push 256", val: 256, expected: []byte{txscript.OP_DATA_2, 0, 0x01}}, + {name: "push 32767", val: 32767, expected: []byte{txscript.OP_DATA_2, 0xff, 0x7f}}, + {name: "push 32768", val: 32768, expected: []byte{txscript.OP_DATA_3, 0, 0x80, 0}}, } - builder := btcscript.NewScriptBuilder() + builder := txscript.NewScriptBuilder() t.Logf("Running %d tests", len(tests)) for i, test := range tests { builder.Reset().AddUint64(test.val) @@ -197,70 +197,70 @@ func TestScriptBuilderAddData(t *testing.T) { useFull bool // use AddFullData instead of AddData. }{ // BIP0062: Pushing an empty byte sequence must use OP_0. - {name: "push empty byte sequence", data: []byte{}, expected: []byte{btcscript.OP_0}}, - {name: "push 1 byte 0x00", data: []byte{0x00}, expected: []byte{btcscript.OP_0}}, + {name: "push empty byte sequence", data: []byte{}, expected: []byte{txscript.OP_0}}, + {name: "push 1 byte 0x00", data: []byte{0x00}, expected: []byte{txscript.OP_0}}, // BIP0062: Pushing a 1-byte sequence of byte 0x01 through 0x10 must use OP_n. - {name: "push 1 byte 0x01", data: []byte{0x01}, expected: []byte{btcscript.OP_1}}, - {name: "push 1 byte 0x02", data: []byte{0x02}, expected: []byte{btcscript.OP_2}}, - {name: "push 1 byte 0x03", data: []byte{0x03}, expected: []byte{btcscript.OP_3}}, - {name: "push 1 byte 0x04", data: []byte{0x04}, expected: []byte{btcscript.OP_4}}, - {name: "push 1 byte 0x05", data: []byte{0x05}, expected: []byte{btcscript.OP_5}}, - {name: "push 1 byte 0x06", data: []byte{0x06}, expected: []byte{btcscript.OP_6}}, - {name: "push 1 byte 0x07", data: []byte{0x07}, expected: []byte{btcscript.OP_7}}, - {name: "push 1 byte 0x08", data: []byte{0x08}, expected: []byte{btcscript.OP_8}}, - {name: "push 1 byte 0x09", data: []byte{0x09}, expected: []byte{btcscript.OP_9}}, - {name: "push 1 byte 0x0a", data: []byte{0x0a}, expected: []byte{btcscript.OP_10}}, - {name: "push 1 byte 0x0b", data: []byte{0x0b}, expected: []byte{btcscript.OP_11}}, - {name: "push 1 byte 0x0c", data: []byte{0x0c}, expected: []byte{btcscript.OP_12}}, - {name: "push 1 byte 0x0d", data: []byte{0x0d}, expected: []byte{btcscript.OP_13}}, - {name: "push 1 byte 0x0e", data: []byte{0x0e}, expected: []byte{btcscript.OP_14}}, - {name: "push 1 byte 0x0f", data: []byte{0x0f}, expected: []byte{btcscript.OP_15}}, - {name: "push 1 byte 0x10", data: []byte{0x10}, expected: []byte{btcscript.OP_16}}, + {name: "push 1 byte 0x01", data: []byte{0x01}, expected: []byte{txscript.OP_1}}, + {name: "push 1 byte 0x02", data: []byte{0x02}, expected: []byte{txscript.OP_2}}, + {name: "push 1 byte 0x03", data: []byte{0x03}, expected: []byte{txscript.OP_3}}, + {name: "push 1 byte 0x04", data: []byte{0x04}, expected: []byte{txscript.OP_4}}, + {name: "push 1 byte 0x05", data: []byte{0x05}, expected: []byte{txscript.OP_5}}, + {name: "push 1 byte 0x06", data: []byte{0x06}, expected: []byte{txscript.OP_6}}, + {name: "push 1 byte 0x07", data: []byte{0x07}, expected: []byte{txscript.OP_7}}, + {name: "push 1 byte 0x08", data: []byte{0x08}, expected: []byte{txscript.OP_8}}, + {name: "push 1 byte 0x09", data: []byte{0x09}, expected: []byte{txscript.OP_9}}, + {name: "push 1 byte 0x0a", data: []byte{0x0a}, expected: []byte{txscript.OP_10}}, + {name: "push 1 byte 0x0b", data: []byte{0x0b}, expected: []byte{txscript.OP_11}}, + {name: "push 1 byte 0x0c", data: []byte{0x0c}, expected: []byte{txscript.OP_12}}, + {name: "push 1 byte 0x0d", data: []byte{0x0d}, expected: []byte{txscript.OP_13}}, + {name: "push 1 byte 0x0e", data: []byte{0x0e}, expected: []byte{txscript.OP_14}}, + {name: "push 1 byte 0x0f", data: []byte{0x0f}, expected: []byte{txscript.OP_15}}, + {name: "push 1 byte 0x10", data: []byte{0x10}, expected: []byte{txscript.OP_16}}, // BIP0062: Pushing the byte 0x81 must use OP_1NEGATE. - {name: "push 1 byte 0x81", data: []byte{0x81}, expected: []byte{btcscript.OP_1NEGATE}}, + {name: "push 1 byte 0x81", data: []byte{0x81}, expected: []byte{txscript.OP_1NEGATE}}, // BIP0062: Pushing any other byte sequence up to 75 bytes must // use the normal data push (opcode byte n, with n the number of // bytes, followed n bytes of data being pushed). - {name: "push 1 byte 0x11", data: []byte{0x11}, expected: []byte{btcscript.OP_DATA_1, 0x11}}, - {name: "push 1 byte 0x80", data: []byte{0x80}, expected: []byte{btcscript.OP_DATA_1, 0x80}}, - {name: "push 1 byte 0x82", data: []byte{0x82}, expected: []byte{btcscript.OP_DATA_1, 0x82}}, - {name: "push 1 byte 0xff", data: []byte{0xff}, expected: []byte{btcscript.OP_DATA_1, 0xff}}, + {name: "push 1 byte 0x11", data: []byte{0x11}, expected: []byte{txscript.OP_DATA_1, 0x11}}, + {name: "push 1 byte 0x80", data: []byte{0x80}, expected: []byte{txscript.OP_DATA_1, 0x80}}, + {name: "push 1 byte 0x82", data: []byte{0x82}, expected: []byte{txscript.OP_DATA_1, 0x82}}, + {name: "push 1 byte 0xff", data: []byte{0xff}, expected: []byte{txscript.OP_DATA_1, 0xff}}, { name: "push data len 17", data: bytes.Repeat([]byte{0x49}, 17), - expected: append([]byte{btcscript.OP_DATA_17}, bytes.Repeat([]byte{0x49}, 17)...), + expected: append([]byte{txscript.OP_DATA_17}, bytes.Repeat([]byte{0x49}, 17)...), }, { name: "push data len 75", data: bytes.Repeat([]byte{0x49}, 75), - expected: append([]byte{btcscript.OP_DATA_75}, bytes.Repeat([]byte{0x49}, 75)...), + expected: append([]byte{txscript.OP_DATA_75}, bytes.Repeat([]byte{0x49}, 75)...), }, // BIP0062: Pushing 76 to 255 bytes must use OP_PUSHDATA1. { name: "push data len 76", data: bytes.Repeat([]byte{0x49}, 76), - expected: append([]byte{btcscript.OP_PUSHDATA1, 76}, bytes.Repeat([]byte{0x49}, 76)...), + expected: append([]byte{txscript.OP_PUSHDATA1, 76}, bytes.Repeat([]byte{0x49}, 76)...), }, { name: "push data len 255", data: bytes.Repeat([]byte{0x49}, 255), - expected: append([]byte{btcscript.OP_PUSHDATA1, 255}, bytes.Repeat([]byte{0x49}, 255)...), + expected: append([]byte{txscript.OP_PUSHDATA1, 255}, bytes.Repeat([]byte{0x49}, 255)...), }, // BIP0062: Pushing 256 to 520 bytes must use OP_PUSHDATA2. { name: "push data len 256", data: bytes.Repeat([]byte{0x49}, 256), - expected: append([]byte{btcscript.OP_PUSHDATA2, 0, 1}, bytes.Repeat([]byte{0x49}, 256)...), + expected: append([]byte{txscript.OP_PUSHDATA2, 0, 1}, bytes.Repeat([]byte{0x49}, 256)...), }, { name: "push data len 520", data: bytes.Repeat([]byte{0x49}, 520), - expected: append([]byte{btcscript.OP_PUSHDATA2, 0x08, 0x02}, bytes.Repeat([]byte{0x49}, 520)...), + expected: append([]byte{txscript.OP_PUSHDATA2, 0x08, 0x02}, bytes.Repeat([]byte{0x49}, 520)...), }, // BIP0062: OP_PUSHDATA4 can never be used, as pushes over 520 @@ -290,7 +290,7 @@ func TestScriptBuilderAddData(t *testing.T) { { name: "push data len 32767 (non-canonical)", data: bytes.Repeat([]byte{0x49}, 32767), - expected: append([]byte{btcscript.OP_PUSHDATA2, 255, 127}, bytes.Repeat([]byte{0x49}, 32767)...), + expected: append([]byte{txscript.OP_PUSHDATA2, 255, 127}, bytes.Repeat([]byte{0x49}, 32767)...), useFull: true, }, @@ -298,12 +298,12 @@ func TestScriptBuilderAddData(t *testing.T) { { name: "push data len 65536 (non-canonical)", data: bytes.Repeat([]byte{0x49}, 65536), - expected: append([]byte{btcscript.OP_PUSHDATA4, 0, 0, 1, 0}, bytes.Repeat([]byte{0x49}, 65536)...), + expected: append([]byte{txscript.OP_PUSHDATA4, 0, 0, 1, 0}, bytes.Repeat([]byte{0x49}, 65536)...), useFull: true, }, } - builder := btcscript.NewScriptBuilder() + builder := txscript.NewScriptBuilder() t.Logf("Running %d tests", len(tests)) for i, test := range tests { if !test.useFull { @@ -328,8 +328,8 @@ func TestExceedMaxScriptSize(t *testing.T) { t.Parallel() // Start off by constructing a max size script. - maxScriptSize := btcscript.TstMaxScriptSize - builder := btcscript.NewScriptBuilder() + maxScriptSize := txscript.TstMaxScriptSize + builder := txscript.NewScriptBuilder() builder.Reset().AddFullData(make([]byte, maxScriptSize-3)) origScript, err := builder.Script() if err != nil { @@ -339,7 +339,7 @@ func TestExceedMaxScriptSize(t *testing.T) { // Ensure adding data that would exceed the maximum size of the script // does not add the data. script, err := builder.AddData([]byte{0x00}).Script() - if _, ok := err.(btcscript.ErrScriptNotCanonical); !ok || err == nil { + if _, ok := err.(txscript.ErrScriptNotCanonical); !ok || err == nil { t.Fatalf("ScriptBuilder.AddData allowed exceeding max script "+ "size: %v", len(script)) } @@ -351,8 +351,8 @@ func TestExceedMaxScriptSize(t *testing.T) { // Ensure adding an opcode that would exceed the maximum size of the // script does not add the data. builder.Reset().AddFullData(make([]byte, maxScriptSize-3)) - script, err = builder.AddOp(btcscript.OP_0).Script() - if _, ok := err.(btcscript.ErrScriptNotCanonical); !ok || err == nil { + script, err = builder.AddOp(txscript.OP_0).Script() + if _, ok := err.(txscript.ErrScriptNotCanonical); !ok || err == nil { t.Fatalf("ScriptBuilder.AddOp unexpected modified script - "+ "got len %d, want len %d", len(script), len(origScript)) } @@ -365,7 +365,7 @@ func TestExceedMaxScriptSize(t *testing.T) { // script does not add the data. builder.Reset().AddFullData(make([]byte, maxScriptSize-3)) script, err = builder.AddInt64(0).Script() - if _, ok := err.(btcscript.ErrScriptNotCanonical); !ok || err == nil { + if _, ok := err.(txscript.ErrScriptNotCanonical); !ok || err == nil { t.Fatalf("ScriptBuilder.AddInt64 unexpected modified script - "+ "got len %d, want len %d", len(script), len(origScript)) } @@ -378,7 +378,7 @@ func TestExceedMaxScriptSize(t *testing.T) { // of the script does not add the data. builder.Reset().AddFullData(make([]byte, maxScriptSize-3)) script, err = builder.AddUint64(0).Script() - if _, ok := err.(btcscript.ErrScriptNotCanonical); !ok || err == nil { + if _, ok := err.(txscript.ErrScriptNotCanonical); !ok || err == nil { t.Fatalf("ScriptBuilder.AddUint64 unexpected modified script - "+ "got len %d, want len %d", len(script), len(origScript)) } @@ -396,15 +396,15 @@ func TestErroredScript(t *testing.T) { // Start off by constructing a near max size script that has enough // space left to add each data type without an error and force an // initial error condition. - maxScriptSize := btcscript.TstMaxScriptSize - builder := btcscript.NewScriptBuilder() + maxScriptSize := txscript.TstMaxScriptSize + builder := txscript.NewScriptBuilder() builder.Reset().AddFullData(make([]byte, maxScriptSize-8)) origScript, err := builder.Script() if err != nil { t.Fatalf("ScriptBuilder.AddFullData unexpected error: %v", err) } script, err := builder.AddData([]byte{0x00, 0x00, 0x00, 0x00, 0x00}).Script() - if _, ok := err.(btcscript.ErrScriptNotCanonical); !ok || err == nil { + if _, ok := err.(txscript.ErrScriptNotCanonical); !ok || err == nil { t.Fatalf("ScriptBuilder.AddData allowed exceeding max script "+ "size: %v", len(script)) } @@ -416,7 +416,7 @@ func TestErroredScript(t *testing.T) { // Ensure adding data, even using the non-canonical path, to a script // that has errored doesn't succeed. script, err = builder.AddFullData([]byte{0x00}).Script() - if _, ok := err.(btcscript.ErrScriptNotCanonical); !ok || err == nil { + if _, ok := err.(txscript.ErrScriptNotCanonical); !ok || err == nil { t.Fatal("ScriptBuilder.AddFullData succeeded on errored script") } if !bytes.Equal(script, origScript) { @@ -427,7 +427,7 @@ func TestErroredScript(t *testing.T) { // Ensure adding data to a script that has errored doesn't succeed. script, err = builder.AddData([]byte{0x00}).Script() - if _, ok := err.(btcscript.ErrScriptNotCanonical); !ok || err == nil { + if _, ok := err.(txscript.ErrScriptNotCanonical); !ok || err == nil { t.Fatal("ScriptBuilder.AddData succeeded on errored script") } if !bytes.Equal(script, origScript) { @@ -437,8 +437,8 @@ func TestErroredScript(t *testing.T) { } // Ensure adding an opcode to a script that has errored doesn't succeed. - script, err = builder.AddOp(btcscript.OP_0).Script() - if _, ok := err.(btcscript.ErrScriptNotCanonical); !ok || err == nil { + script, err = builder.AddOp(txscript.OP_0).Script() + if _, ok := err.(txscript.ErrScriptNotCanonical); !ok || err == nil { t.Fatal("ScriptBuilder.AddOp succeeded on errored script") } if !bytes.Equal(script, origScript) { @@ -449,7 +449,7 @@ func TestErroredScript(t *testing.T) { // Ensure adding an integer to a script that has errored doesn't // succeed. script, err = builder.AddInt64(0).Script() - if _, ok := err.(btcscript.ErrScriptNotCanonical); !ok || err == nil { + if _, ok := err.(txscript.ErrScriptNotCanonical); !ok || err == nil { t.Fatal("ScriptBuilder.AddInt64 succeeded on errored script") } if !bytes.Equal(script, origScript) { @@ -460,7 +460,7 @@ func TestErroredScript(t *testing.T) { // Ensure adding an unsigned integer to a script that has errored // doesn't succeed. script, err = builder.AddUint64(0).Script() - if _, ok := err.(btcscript.ErrScriptNotCanonical); !ok || err == nil { + if _, ok := err.(txscript.ErrScriptNotCanonical); !ok || err == nil { t.Fatal("ScriptBuilder.AddUint64 succeeded on errored script") } if !bytes.Equal(script, origScript) { diff --git a/stack.go b/txscript/stack.go similarity index 99% rename from stack.go rename to txscript/stack.go index 19aadf9f..c2fdba4a 100644 --- a/stack.go +++ b/txscript/stack.go @@ -1,8 +1,8 @@ -// Copyright (c) 2013-2014 Conformal Systems LLC. +// Copyright (c) 2013-2015 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. -package btcscript +package txscript import ( "encoding/hex" diff --git a/stack_test.go b/txscript/stack_test.go similarity index 78% rename from stack_test.go rename to txscript/stack_test.go index 0da1f1d6..63dab488 100644 --- a/stack_test.go +++ b/txscript/stack_test.go @@ -1,8 +1,8 @@ -// Copyright (c) 2013-2014 Conformal Systems LLC. +// Copyright (c) 2013-2015 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. -package btcscript_test +package txscript_test import ( "bytes" @@ -11,7 +11,7 @@ import ( "math/big" "testing" - "github.com/btcsuite/btcscript" + "github.com/btcsuite/btcd/txscript" ) // TestStack tests that all of the stack operations work as expected. @@ -21,14 +21,14 @@ func TestStack(t *testing.T) { tests := []struct { name string before [][]byte - operation func(*btcscript.Stack) error + operation func(*txscript.Stack) error expectedReturn error after [][]byte }{ { "noop", [][]byte{{1}, {2}, {3}, {4}, {5}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return nil }, nil, @@ -37,37 +37,37 @@ func TestStack(t *testing.T) { { "peek underflow (byte)", [][]byte{{1}, {2}, {3}, {4}, {5}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { _, err := stack.PeekByteArray(5) return err }, - btcscript.ErrStackUnderflow, + txscript.ErrStackUnderflow, [][]byte{}, }, { "peek underflow (int)", [][]byte{{1}, {2}, {3}, {4}, {5}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { _, err := stack.PeekInt(5) return err }, - btcscript.ErrStackUnderflow, + txscript.ErrStackUnderflow, [][]byte{}, }, { "peek underflow (bool)", [][]byte{{1}, {2}, {3}, {4}, {5}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { _, err := stack.PeekBool(5) return err }, - btcscript.ErrStackUnderflow, + txscript.ErrStackUnderflow, [][]byte{}, }, { "pop", [][]byte{{1}, {2}, {3}, {4}, {5}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { val, err := stack.PopByteArray() if err != nil { return err @@ -83,7 +83,7 @@ func TestStack(t *testing.T) { { "pop", [][]byte{{1}, {2}, {3}, {4}, {5}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { val, err := stack.PopByteArray() if err != nil { return err @@ -99,7 +99,7 @@ func TestStack(t *testing.T) { { "pop everything", [][]byte{{1}, {2}, {3}, {4}, {5}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { for i := 0; i < 5; i++ { _, err := stack.PopByteArray() if err != nil { @@ -114,7 +114,7 @@ func TestStack(t *testing.T) { { "pop underflow", [][]byte{{1}, {2}, {3}, {4}, {5}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { for i := 0; i < 6; i++ { _, err := stack.PopByteArray() if err != nil { @@ -123,13 +123,13 @@ func TestStack(t *testing.T) { } return nil }, - btcscript.ErrStackUnderflow, + txscript.ErrStackUnderflow, [][]byte{}, }, { "pop bool", [][]byte{{0}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { val, err := stack.PopBool() if err != nil { return err @@ -146,7 +146,7 @@ func TestStack(t *testing.T) { { "pop bool", [][]byte{{1}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { val, err := stack.PopBool() if err != nil { return err @@ -163,7 +163,7 @@ func TestStack(t *testing.T) { { "pop bool", [][]byte{}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { _, err := stack.PopBool() if err != nil { return err @@ -171,13 +171,13 @@ func TestStack(t *testing.T) { return nil }, - btcscript.ErrStackUnderflow, + txscript.ErrStackUnderflow, [][]byte{}, }, { "popInt 0", [][]byte{{0x0}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { v, err := stack.PopInt() if err != nil { return err @@ -193,7 +193,7 @@ func TestStack(t *testing.T) { { "popInt -0", [][]byte{{0x80}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { v, err := stack.PopInt() if err != nil { return err @@ -209,7 +209,7 @@ func TestStack(t *testing.T) { { "popInt 1", [][]byte{{0x01}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { v, err := stack.PopInt() if err != nil { return err @@ -225,7 +225,7 @@ func TestStack(t *testing.T) { { "popInt 1 leading 0", [][]byte{{0x01, 0x00, 0x00, 0x00}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { v, err := stack.PopInt() if err != nil { return err @@ -242,7 +242,7 @@ func TestStack(t *testing.T) { { "popInt -1", [][]byte{{0x81}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { v, err := stack.PopInt() if err != nil { return err @@ -258,7 +258,7 @@ func TestStack(t *testing.T) { { "popInt -1 leading 0", [][]byte{{0x01, 0x00, 0x00, 0x80}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { v, err := stack.PopInt() if err != nil { return err @@ -276,7 +276,7 @@ func TestStack(t *testing.T) { { "popInt -513", [][]byte{{0x1, 0x82}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { v, err := stack.PopInt() if err != nil { return err @@ -294,7 +294,7 @@ func TestStack(t *testing.T) { { "peekint nomodify -1", [][]byte{{0x01, 0x00, 0x00, 0x80}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { v, err := stack.PeekInt(0) if err != nil { return err @@ -311,7 +311,7 @@ func TestStack(t *testing.T) { { "PushInt 0", [][]byte{}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { stack.PushInt(big.NewInt(0)) return nil }, @@ -321,7 +321,7 @@ func TestStack(t *testing.T) { { "PushInt 1", [][]byte{}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { stack.PushInt(big.NewInt(1)) return nil }, @@ -331,7 +331,7 @@ func TestStack(t *testing.T) { { "PushInt -1", [][]byte{}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { stack.PushInt(big.NewInt(-1)) return nil }, @@ -341,7 +341,7 @@ func TestStack(t *testing.T) { { "PushInt two bytes", [][]byte{}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { stack.PushInt(big.NewInt(256)) return nil }, @@ -352,7 +352,7 @@ func TestStack(t *testing.T) { { "PushInt leading zeros", [][]byte{}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { // this will have the highbit set stack.PushInt(big.NewInt(128)) return nil @@ -363,7 +363,7 @@ func TestStack(t *testing.T) { { "dup", [][]byte{{1}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { err := stack.DupN(1) if err != nil { return err @@ -377,7 +377,7 @@ func TestStack(t *testing.T) { { "dup2", [][]byte{{1}, {2}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { err := stack.DupN(2) if err != nil { return err @@ -391,7 +391,7 @@ func TestStack(t *testing.T) { { "dup3", [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { err := stack.DupN(3) if err != nil { return err @@ -405,7 +405,7 @@ func TestStack(t *testing.T) { { "dup0", [][]byte{{1}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { err := stack.DupN(0) if err != nil { return err @@ -413,13 +413,13 @@ func TestStack(t *testing.T) { return nil }, - btcscript.ErrStackInvalidArgs, + txscript.ErrStackInvalidArgs, [][]byte{}, }, { "dup-1", [][]byte{{1}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { err := stack.DupN(-1) if err != nil { return err @@ -427,13 +427,13 @@ func TestStack(t *testing.T) { return nil }, - btcscript.ErrStackInvalidArgs, + txscript.ErrStackInvalidArgs, [][]byte{}, }, { "dup too much", [][]byte{{1}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { err := stack.DupN(2) if err != nil { return err @@ -441,13 +441,13 @@ func TestStack(t *testing.T) { return nil }, - btcscript.ErrStackUnderflow, + txscript.ErrStackUnderflow, [][]byte{}, }, { "dup-1", [][]byte{{1}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { err := stack.DupN(-1) if err != nil { return err @@ -455,13 +455,13 @@ func TestStack(t *testing.T) { return nil }, - btcscript.ErrStackInvalidArgs, + txscript.ErrStackInvalidArgs, [][]byte{}, }, { "PushBool true", [][]byte{}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { stack.PushBool(true) return nil @@ -472,7 +472,7 @@ func TestStack(t *testing.T) { { "PushBool false", [][]byte{}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { stack.PushBool(false) return nil @@ -483,7 +483,7 @@ func TestStack(t *testing.T) { { "PushBool PopBool", [][]byte{}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { stack.PushBool(true) val, err := stack.PopBool() if err != nil { @@ -501,7 +501,7 @@ func TestStack(t *testing.T) { { "PushBool PopBool 2", [][]byte{}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { stack.PushBool(false) val, err := stack.PopBool() if err != nil { @@ -519,7 +519,7 @@ func TestStack(t *testing.T) { { "PushInt PopBool", [][]byte{}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { stack.PushInt(big.NewInt(1)) val, err := stack.PopBool() if err != nil { @@ -537,7 +537,7 @@ func TestStack(t *testing.T) { { "PushInt PopBool 2", [][]byte{}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { stack.PushInt(big.NewInt(0)) val, err := stack.PopBool() if err != nil { @@ -555,7 +555,7 @@ func TestStack(t *testing.T) { { "PushInt PopBool 2", [][]byte{}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { stack.PushInt(big.NewInt(0)) val, err := stack.PopBool() if err != nil { @@ -573,7 +573,7 @@ func TestStack(t *testing.T) { { "Nip top", [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.NipN(0) }, nil, @@ -582,7 +582,7 @@ func TestStack(t *testing.T) { { "Nip middle", [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.NipN(1) }, nil, @@ -591,7 +591,7 @@ func TestStack(t *testing.T) { { "Nip low", [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.NipN(2) }, nil, @@ -600,27 +600,27 @@ func TestStack(t *testing.T) { { "Nip too much", [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { // bite off more than we can chew return stack.NipN(3) }, - btcscript.ErrStackUnderflow, + txscript.ErrStackUnderflow, [][]byte{{2}, {3}}, }, { "Nip too much", [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { // bite off more than we can chew return stack.NipN(3) }, - btcscript.ErrStackUnderflow, + txscript.ErrStackUnderflow, [][]byte{{2}, {3}}, }, { "keep on tucking", [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.Tuck() }, nil, @@ -629,25 +629,25 @@ func TestStack(t *testing.T) { { "a little tucked up", [][]byte{{1}}, // too few arguments for tuck - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.Tuck() }, - btcscript.ErrStackUnderflow, + txscript.ErrStackUnderflow, [][]byte{}, }, { "all tucked up", [][]byte{}, // too few arguments for tuck - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.Tuck() }, - btcscript.ErrStackUnderflow, + txscript.ErrStackUnderflow, [][]byte{}, }, { "drop 1", [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.DropN(1) }, nil, @@ -656,7 +656,7 @@ func TestStack(t *testing.T) { { "drop 2", [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.DropN(2) }, nil, @@ -665,7 +665,7 @@ func TestStack(t *testing.T) { { "drop 3", [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.DropN(3) }, nil, @@ -674,7 +674,7 @@ func TestStack(t *testing.T) { { "drop 4", [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.DropN(4) }, nil, @@ -683,25 +683,25 @@ func TestStack(t *testing.T) { { "drop 4/5", [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.DropN(5) }, - btcscript.ErrStackUnderflow, + txscript.ErrStackUnderflow, [][]byte{}, }, { "drop invalid", [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.DropN(0) }, - btcscript.ErrStackInvalidArgs, + txscript.ErrStackInvalidArgs, [][]byte{}, }, { "Rot1", [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.RotN(1) }, nil, @@ -710,7 +710,7 @@ func TestStack(t *testing.T) { { "Rot2", [][]byte{{1}, {2}, {3}, {4}, {5}, {6}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.RotN(2) }, nil, @@ -719,25 +719,25 @@ func TestStack(t *testing.T) { { "Rot too little", [][]byte{{1}, {2}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.RotN(1) }, - btcscript.ErrStackUnderflow, + txscript.ErrStackUnderflow, [][]byte{}, }, { "Rot0", [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.RotN(0) }, - btcscript.ErrStackInvalidArgs, + txscript.ErrStackInvalidArgs, [][]byte{}, }, { "Swap1", [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.SwapN(1) }, nil, @@ -746,7 +746,7 @@ func TestStack(t *testing.T) { { "Swap2", [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.SwapN(2) }, nil, @@ -755,25 +755,25 @@ func TestStack(t *testing.T) { { "Swap too little", [][]byte{{1}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.SwapN(1) }, - btcscript.ErrStackUnderflow, + txscript.ErrStackUnderflow, [][]byte{}, }, { "Swap0", [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.SwapN(0) }, - btcscript.ErrStackInvalidArgs, + txscript.ErrStackInvalidArgs, [][]byte{}, }, { "Over1", [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.OverN(1) }, nil, @@ -782,7 +782,7 @@ func TestStack(t *testing.T) { { "Over2", [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.OverN(2) }, nil, @@ -791,25 +791,25 @@ func TestStack(t *testing.T) { { "Over too little", [][]byte{{1}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.OverN(1) }, - btcscript.ErrStackUnderflow, + txscript.ErrStackUnderflow, [][]byte{}, }, { "Over0", [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.OverN(0) }, - btcscript.ErrStackInvalidArgs, + txscript.ErrStackInvalidArgs, [][]byte{}, }, { "Pick1", [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.PickN(1) }, nil, @@ -818,7 +818,7 @@ func TestStack(t *testing.T) { { "Pick2", [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.PickN(2) }, nil, @@ -827,16 +827,16 @@ func TestStack(t *testing.T) { { "Pick too little", [][]byte{{1}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.PickN(1) }, - btcscript.ErrStackUnderflow, + txscript.ErrStackUnderflow, [][]byte{}, }, { "Roll1", [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.RollN(1) }, nil, @@ -845,7 +845,7 @@ func TestStack(t *testing.T) { { "Roll2", [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.RollN(2) }, nil, @@ -854,16 +854,16 @@ func TestStack(t *testing.T) { { "Roll too little", [][]byte{{1}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { return stack.RollN(1) }, - btcscript.ErrStackUnderflow, + txscript.ErrStackUnderflow, [][]byte{}, }, { "Peek bool", [][]byte{{1}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { // Peek bool is otherwise pretty well tested, // just check it works. val, err := stack.PeekBool(0) @@ -881,7 +881,7 @@ func TestStack(t *testing.T) { { "Peek bool 2", [][]byte{{0}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { // Peek bool is otherwise pretty well tested, // just check it works. val, err := stack.PeekBool(0) @@ -899,7 +899,7 @@ func TestStack(t *testing.T) { { "Peek int", [][]byte{{1}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { // Peek int is otherwise pretty well tested, // just check it works. val, err := stack.PeekInt(0) @@ -917,7 +917,7 @@ func TestStack(t *testing.T) { { "Peek int 2", [][]byte{{0}}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { // Peek int is otherwise pretty well tested, // just check it works. val, err := stack.PeekInt(0) @@ -935,7 +935,7 @@ func TestStack(t *testing.T) { { "pop int", [][]byte{}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { stack.PushInt(big.NewInt(1)) // Peek int is otherwise pretty well tested, // just check it works. @@ -954,19 +954,19 @@ func TestStack(t *testing.T) { { "pop empty", [][]byte{}, - func(stack *btcscript.Stack) error { + func(stack *txscript.Stack) error { // Peek int is otherwise pretty well tested, // just check it works. _, err := stack.PopInt() return err }, - btcscript.ErrStackUnderflow, + txscript.ErrStackUnderflow, [][]byte{}, }, } for _, test := range tests { - stack := btcscript.Stack{} + stack := txscript.Stack{} for i := range test.before { stack.PushByteArray(test.before[i])